/***********************************************************************
 * Copyright (c)  2017 - 2022, Unicmicro Co.,Ltd .
 * All rights reserved.
 * Filename    : qspi.h
 * Description : qspi header file
 * Author(s)   : zhilan
 * version     : V1.0
 * Modify date : 2022-08-04
 ***********************************************************************/
#ifndef __QSPI_H__
#define __QSPI_H__

#include  "um321xF.h"

#define EXT_FLASH_START_ADDR		0x10000			//starting address of external flash

#define SIN_MODDE					1
#define DUAL_MODE					2
#define QUAD_MODE					4

#define QSPI_MODE					SIN_MODDE      //qspi通信模式

//QSPI FLASH CMD W25QL128
#define READ_DATA_BYTES           					0x03
#define READ_DATA_BYTES_FAST           				0x0B
#define	DUAL_IO_FAST_READ                   		0xBB
#define	DUAL_OUTPUT_FAST_READ               		0x3B
#define	QUAD_IO_FAST_READ                   		0xEB
#define	QUAD_OUTPUT_FAST_READ               		0x6B
#define PAGE_PROGRAM					 			0x02
#define QUAD_PAGE_PROGRAM					 		0x32
#define SECTOR_ERASE   					 			0x20
#define BLOCK_ERASE_32KB                   			0x52
#define BLOCK_ERASE_64KB                  			0xD8
#define CHIP_ERASE                        			0x60 
#define WRITE_ENABLE   					 			0x06
#define WRITE_DISABLE                 	 			0x04
#define READ_FLASH_STATUS   			 			0x05 
#define READ_FLASH_CONFIGURATION			 		0x15 
#define	WRITE_STATUS_REG              				0x31 
#define DEEP_POWER_DOWN                    			0xB9 
#define FLASH_ID               			 			0x9F
#define READ_DEVICE_ID        			 			0x90
#define ENABLE_RESET_MEMORY               			0x99

#define SPI_FLASH_PER_WRITE_PAGESIZE     			256
#define SPI_FLASH_PAGESIZE               			256
 
#define QSPI_IRQ_ENABLE  			(1)             //qspi 中断使能
#define QSPI_IRQ_DISABLE  			(0)             //qspi 中断失能

#define CPU_HOLD									//hold cpu while writing ext flash 

#define QSPI_LINE_1  				(0<<3)		    //单数据线SPI协议传输；（标准SPI协议）
#define QSPI_LINE_2  				(1<<3)		    //2数据线SPI协议传输
#define QSPI_LINE_4  				(2<<3)			//4数据线SPI协议传输	

#define QSPI_LSB  			    	(1<<2)		    //SPI总线传输中LSB在前
#define QSPI_MSB   				    (0<<2)          //SPI总线传输中MSB在前

#define WORK_MODE_0  				(0<<0)			//SPI0工作模式0:CPHOL = 0 CPHA = 0
#define WORK_MODE_1  				(1<<0)			//SPI0工作模式1:CPHOL = 0 CPHA = 1
#define WORK_MODE_2  				(2<<0)			//SPI0工作模式2:CPHOL = 1 CPHA = 0
#define WORK_MODE_3  				(3<<0)			//SPI0工作模式3:CPHOL = 1 CPHA = 1

#define WRITE_NORMAL                (1<<20)			//使能普通SPI写模式，不发送地址和数据字段
#define READ_NORMAL                 (1<<19)			//使能普通SPI读模式，不发送地址和数据字段

#define ADDR_LINE_SIZE_R            (1<<18)			//line size of addr when reading

#define Para_No2R_0                 (0<<16)			//读操作: 不使用参数2
#define Para_No2R_1                 (1<<16)			//参数2长度为1个byte
#define Para_No2R_2                 (2<<16)			//参数2长度为2个byte

#define Para_No1R_0                 (0<<15)			//不使用参数1
#define Para_No1R_1                 (1<<15)			//使用参数1，参数1为一个byte 

#define Para_Ord2R_BEFORE           (0<<14)			//读操作决定在发送地址前加入参数2
#define Para_Ord2R_AFTER            (1<<14)			//读操作决定在发送地址后加入参数2

#define Para_Ord1R_BEFORE           (0<<13)			//读操作决定在发送地址前加入参数1
#define Para_Ord1R_AFTER            (1<<13)			//读操作决定在发送地址后加入参数1

#define WRITE_HAVE_DATA             (0<<12)			//写操作含有数据字段
#define WRITE_NO_DATA               (1<<12)			//写操作没有数据字段

#define READ_HAVE_ADDR              (0<<11)			//读操作发送Addr字段
#define READ_NO_ADDR                (1<<11)			//读操作不发送ADDR字段

#define WRITE_HAVE_ADDR             (0<<10)			//写操作发送Addr字段
#define WRITE_NO_ADDR               (1<<10)			//写操作不发送ADDR字段

#define ADDR_LINE_SIZE_W            (1<<9)			//line size of addr when writing

#define ADDR_WIDTH_1                (0<<7)			//地址位宽为1个字节
#define ADDR_WIDTH_2                (1<<7)			//地址位宽为2个字节
#define ADDR_WIDTH_3                (2<<7)			//地址位宽为3个字节

#define Para_No2W_0                 (0<<5)			//擦写操作: 不使用参数2
#define Para_No2W_1                 (1<<5)			//参数2长度为1个byte
#define Para_No2W_2                 (2<<5)			//参数2长度为2个byte
				
#define Para_No1W_0                 (0<<4)			//不使用参数1
#define Para_No1W_1                 (1<<4)			//使用参数1，参数1为一个byte 

#define CON_RD_EN                   (1<<3)			//使能连读

#define Para_Ord2W_BEFORE           (0<<2)			//擦写操作决定在发送地址前加入参数2
#define Para_Ord2W_AFTER            (1<<2)			//擦写操作决定在发送地址后加入参数2
				 
#define Para_Ord1W_BEFORE           (0<<1)			//擦写操作决定在发送地址前加入参数1
#define Para_Ord1W_AFTER            (1<<1)			//擦写操作决定在发送地址后加入参数1

#define QSPI_EN                     (1<<0)			//使能SPI

#define QSPI_DONEEN                 (1<<0)			//完成中断使能
#define QSPI_OPERREN                (1<<1)			//错误操作中断使能

#define QSPI_DONE_STATUS            (1<<0)			//完成中断产生
#define QSPI_OPERR_STATUS           (1<<1)			//错误中断产生

#define QSPI_DONE_CLEAR             (1<<0)			//清除完成中断
#define QSPI_OPERR_CLEAR            (1<<1)			//清除错误中断

#define QSPI_READY                  (1<<0)			//SPI_ACC模块空闲
#define QSPI_BUSY                   (0<<0)			//SPI_ACC模块忙，正在进行FLASH操作
 			
#define QSPI_DONEEN_INT_ENABLE		(1)
#define QSPI_OPERREN_INT_ENABLE		(2)

#define QSPI_CMD_WR					(1)             //qspi 指令为写
#define QSPI_CMD_RD					(2)             //qspi 指令为读

/************************************************************************
 * function    : qspi_init
 * description : qspi initial
 * input 	   : uint8_t qspi_line : qspi communication mode
 *				 uint8_t work_mode:  set CPHOL and CPHA
 *				 uint16_t qspi_baud: qspi communication rate  The minimum setting is 2 and multiple writing of 2 is required.
 * return	   : none
 ************************************************************************/
void qspi_init(uint8_t qspi_line,uint8_t work_mode,uint16_t qspi_baud);

/************************************************************************
 * function    : qspi_irq_init
 * description : qspi irq initial
 * input 	   : uint8_t state:  	enable/disable	 
 *				 void (*pfunc)():	callback handler function		
 * return	   : none
 ************************************************************************/
void qspi_irq_init( uint8_t state, void (*pfunc)());

/************************************************************************
 * function    : qspi_line_set
 * description : set line of qspi
 * input 	   : uint8_t  line	Qspi communication mode in 1-wire, 2-wire, 4-wire
 * return	   : none
 ************************************************************************/
void qspi_line_set(uint8_t line);

/************************************************************************
 * function    : qspi_config
 * description : config the frame of qspi
 * input 	   : uint32_t cfg cfg parameters 
 * return	   : none
 ************************************************************************/
void qspi_config(uint32_t cfg);

/************************************************************************
 * function    : qspi_set_cmd
 * description : set the command 
 * input 	   : uint8_t type :	read/write
 *				 uint8_t cmd:	command 
 * return	   : none
 ************************************************************************/
void qspi_set_cmd(uint8_t type,uint8_t cmd);

/************************************************************************
 * function    : qspi_set_program_time
 * description : set the waiting time of programing
 * input 	   : uint16_t tim: time to wait,rely on HALF_US
 * return	   : none
 ************************************************************************/
void qspi_set_program_time(uint16_t tim);

/************************************************************************
 * function    : qspi_set_para_read
 * description : set the parameter while reading
 * input 	   : uint8_t para1 : read command parameter 1
 * 		 	   : uint16_t para2 :read command parameter 2
 * return	   : none
 ************************************************************************/
void qspi_set_para_read(uint8_t para1, uint16_t para2);

/************************************************************************
 * function    : qspi_set_para_write
 * description : set the parameter while writing
 * input 	   : uint8_t para1 : write command parameter 1
 * 		 	   : uint16_t para2 :write command parameter 2
 * return	   : none
 ************************************************************************/
void qspi_set_para_write(uint8_t para1, uint16_t para2);

/************************************************************************
 * function    : qspi_read_byte
 * description : read byte from EXT_FLASH_START_ADDR+offset
 * input 	   : uint32_t offset: offset of address to read
 * return	   : none
 ************************************************************************/
uint8_t qspi_read_byte(uint32_t offset);

/************************************************************************
 * function    : qspi_read_word
 * description : read word from EXT_FLASH_START_ADDR+offset
 * input 	   : uint32_t offset ： offset of address to read
 * return	   : none
 ************************************************************************/
uint16_t qspi_read_word(uint32_t offset);

/************************************************************************
 * function    : qspi_read_dword
 * description : read 1 double-word from EXT_FLASH_START_ADDR+offset
 * input 	   : uint32_t offset: offset of address to read
 * return	   : none
 ************************************************************************/
uint32_t qspi_read_dword(uint32_t offset);

/************************************************************************
 * function    : qspi_write_byte
 * description : write byte from EXT_FLASH_START_ADDR+offset
 * input 	   : uint32_t offset: offset of address to write
				 uint8_t val:	value to write 
 * return	   : none
 ************************************************************************/
void qspi_write_byte(uint32_t offset, uint8_t val);

/************************************************************************
 * function    : qspi_write_word
 * description : write word from EXT_FLASH_START_ADDR+offset
 * input 	   : uint32_t offset: offset of address to write
				 uint16_t val:	value to write 
 * return	   : none
 ************************************************************************/
void qspi_write_word(uint32_t offset, uint16_t val);

/************************************************************************
 * function    : qspi_write_dword
 * description : write double-word from EXT_FLASH_START_ADDR+offset
 * input 	   : uint32_t offset: offset of address to write
				 uint32_t val:	value to write 
 * return	   : none
 ************************************************************************/
void qspi_write_dword(uint32_t offset, uint32_t val);
  
/************************************************************************
 * function    : 	flash_read_device_id
 * Description : 	read flash's deive number	
 * input	   : 	NULL
 * return	   : 	device num
 ************************************************************************/
uint16_t flash_read_device_id(void);

/************************************************************************
 * function    : flash_write_enable
 * description : enable the write function of flash
 * input	   : none
 * return	   : none
 ************************************************************************/
void flash_write_enable(void);
/************************************************************************
 * function    : flash_wait_till_idle
 * description : wait untill flash is idle
 * input	   : none
 * return	   : none
 ************************************************************************/
void flash_wait_till_idle(void);
/************************************************************************
 * function    : flash_write_disable
 * description : disable the write function of flash
 * input	   : none
 * return	   : none
 ************************************************************************/
void flash_write_disable(void);

/************************************************************************
 * function    : flash_wait_till_idle
 * description : wait untill flash is idle
 * input	   : none
 * return	   : none
 ************************************************************************/
void flash_wait_till_idle(void);

/************************************************************************
 * function    : flash_read_id
 * description : read flash's identifier	
 * input	   : none
 * return	   : flash id
 ************************************************************************/
uint32_t flash_read_id(void);
/************************************************************************
 * function    : flash_read_device_id
 * description : read flash's deive number	
 * input	   : none
 * return	   : manufacture id
 ************************************************************************/
uint16_t flash_read_device_id(void);

/************************************************************************
 * function    : erase_flash_sector
 * description : erase flash sector
 * input	   : starting address of the sector 
 * return	   : none
 ************************************************************************/
void erase_flash_sector(uint32_t erase_add);

/************************************************************************
 * function    : flash_write_page
 * description : program page of flash using 1-line
 * input	   : uint8_t* buffer:	buffer which store the data
 *				 uint32_t write_addr: the starting address of page
 *				 uint16_tlen: length of the buffer to write
 * return	   : none
 ************************************************************************/
void flash_write_page(uint8_t* buffer,uint32_t write_addr,uint16_t len);

/************************************************************************
 * function    : flash_4write_page
 * description : program page of flash using 4-line
 * input	   : uint8_t* buffer:	buffer which store the data
 *				 uint32_t write_addr: the starting address of page
 *				 uint16_t len: length of the buffer to write
 * return	   : none
 ************************************************************************/
void flash_4write_page(uint8_t* buffer,uint32_t write_addr,uint16_t len);
/************************************************************************
 * function    : flash_4read_bytes
 * description : rad data from flash using 4-line
 * input	   : uint8_t* buffer:	buffer which store the data
 *				 uint32_t read_addr: the starting address of data
 *				 uint16_t len: length of the buffer to read
 * return	   : none
 ************************************************************************/
void flash_4read_bytes(uint8_t* buffer,uint32_t read_addr,uint16_t len);
/************************************************************************
 * function    : flash_read_bytes
 * description : rad data from flash using 1-line
 * input	   : uint8_t* buffer:	buffer which store the data
 *				 uint32_t read_addr: the starting address of data
 *				 uint16_t len: length of the buffer to read			 
 * return	   : none
 ************************************************************************/
void flash_read_bytes(uint8_t* buffer,uint32_t read_addr,uint16_t len);
/************************************************************************
 * function    : flash_2read_bytes
 * description : rad data from flash using 2-line
 * input	   : uint8_t* buffer:	buffer which store the data
 *				 uint32_t read_addr: the starting address of data
 *				 uint16_t len: length of the buffer to read
 * return	   : none
 ************************************************************************/
void flash_2read_bytes(uint8_t* buffer,uint32_t read_addr,uint16_t len);
/************************************************************************
 * function    : flash_quad_disable
 * description : disable the quad mode 
 * input	   : none
 * return	   : none
 ************************************************************************/
void flash_quad_disable(void);
/************************************************************************
 * function    : flash_quad_enable
 * description : enable the quad mode 
 * input	   : none
 * return	   : none
 ************************************************************************/
void flash_quad_enable(void);
/************************************************************************
 * function    : flash_enter_quad_fast_mode
 * description : set flash into 4-line fast read mode
 * input	   : none
 * return	   : none
 ************************************************************************/
void flash_enter_quad_fast_mode(void);

#endif


