/******************************************************************************
 * @file      drv_w5500.h
 * @brief     w5500 drivers
 * @version   V1.0
 * @author    Gary
 * @copyright
 ******************************************************************************/
#ifndef DRV_W5500_H_
#define DRV_W5500_H_

#include <stdint.h>
#include "drv_spi.h"

#define W5500_PRT_EN                            false
#define W5500_READ_ACCESS_MODE                  (0u)
#define W5500_WRITE_ACCESS_MODE                 (4u)
#define W5500_MAX_SOCKET_NUM                    (8u)
#define W5500_MAX_READ_BUF_SIZE                 (2048u)
#define W5500_CREAT_SOCKET_REG(socket)          ((socket) << 2 | 0x01)
#define W5500_CREAT_SOCKET_WRITE_BUF(socket)    ((socket) << 2 | 0x02)
#define W5500_CREAT_SOCKET_READ_BUF(socket)     ((socket) << 2 | 0x03)

#define Sn_IR_SEND_OK                0x10     /**< complete sending */


//寄存器选择定义
typedef enum
{
	SELECT_GREG_00		    	=	0,	//通用寄存器
	SELECT_SECKET0_01	        =	1,	//socket0寄存器
	SELECT_SECKET1_05	        =	5,	//socket1寄存器
	SELECT_SECKET2_09   	    =	9,	//socket2寄存器
	SELECT_SECKET3_13   	    =	13,	//socket3寄存器
	SELECT_SECKET4_17   	    =	17,	//socket4寄存器
	SELECT_SECKET5_21       	=	21,	//socket5寄存器
	SELECT_SECKET6_25       	=	25,	//socket6寄存器
	SELECT_SECKET7_29       	=	29,	//socket7寄存器
	SELECT_SECKET0_TXREG_02 	=	2,	//socket0发送缓冲区
	SELECT_SECKET1_TXREG_06	    =	6,	//socket0发送缓冲区
	SELECT_SECKET2_TXREG_10 	=	10,	//socket0发送缓冲区
	SELECT_SECKET3_TXREG_14	    =	14,	//socket0发送缓冲区
	SELECT_SECKET4_TXREG_18	    =	18,	//socket0发送缓冲区
	SELECT_SECKET5_TXREG_22 	=	22,	//socket0发送缓冲区
	SELECT_SECKET6_TXREG_26 	=	26,	//socket0发送缓冲区
	SELECT_SECKET7_TXREG_30 	=	30,	//socket0发送缓冲区
	SELECT_SECKET0_RXREG_03 	=	3,	//socket0接收缓冲区
	SELECT_SECKET1_RXREG_07	    =	7,	//socket0接收缓冲区
	SELECT_SECKET2_RXREG_11	    =	11,	//socket0接收缓冲区
	SELECT_SECKET3_RXREG_15	    =	15,	//socket0接收缓冲区
	SELECT_SECKET4_RXREG_19	    =	19,	//socket0接收缓冲区
	SELECT_SECKET5_RXREG_23	    =	23,	//socket0接收缓冲区
	SELECT_SECKET6_RXREG_27	    =	27,	//socket0接收缓冲区
	SELECT_SECKET7_RXREG_31 	=	31,	//socket0接收缓冲区
}W5500_BLOCK_SELECT;

//通用寄存器地址定义
typedef enum 
{
	W5500_MODE_REG_0x00		    =	0x0000,	//模式寄存器
	W5500_GAR0_REG_0x01 		=	0x0001,	//网关地址字节1
	W5500_GAR1_REG_0x02 		=	0x0002,	//网关地址字节2
	W5500_GAR2_REG_0x03 		=	0x0003,	//网关地址字节3
	W5500_GAR3_REG_0x04 		=	0x0004,	//网关地址字节4
	W5500_SUBR0_REG_0x05		=	0x0005,	//子网掩码字节1
	W5500_SUBR1_REG_0x06		=	0x0006,	//子网掩码字节2
	W5500_SUBR2_REG_0x07		=	0x0007,	//子网掩码字节3
	W5500_SUBR3_REG_0x08		=	0x0008,	//子网掩码字节4
	W5500_SHAR0_REG_0x09		=	0x0009,	//MAC硬件地址字节1
	W5500_SHAR1_REG_0x0A		=	0x000A,	//MAC硬件地址字节2
	W5500_SHAR2_REG_0x0B		=	0x000B,	//MAC硬件地址字节3
	W5500_SHAR3_REG_0x0C		=	0x000C,	//MAC硬件地址字节4
	W5500_SHAR4_REG_0x0D		=	0x000D,	//MAC硬件地址字节5
	W5500_SHAR5_REG_0x0E		=	0x000E,	//MAC硬件地址字节6
	W5500_SIPR0_REG_0x0F		=	0x000F,	//本地IP字节1
	W5500_SIPR1_REG_0x10		=	0x0010,	//本地IP字节2
	W5500_SIPR2_REG_0x11		=	0x0011,	//本地IP字节3
	W5500_SIPR3_REG_0x12		=	0x0012,	//本地IP字节4
	W5500_INTLEVEL0_REG_0x13	=	0x0013,	//低电平中断定时器寄存器-高字节
	W5500_INTLEVEL1_REG_0x14	=	0x0014,	//低电平中断定时器寄存器-低字节
	W5500_IR_REG_0x15   		=	0x0015,	//中断寄存器
	W5500_IMR_REG_0x16  		=	0x0016,	//中断 屏蔽 寄存器
	W5500_SIR_REG_0x17	    	=	0x0017,	//Socket 中断寄存器
	W5500_SIMR_REG_0x18 		=	0x0018,	//Socket 中断屏蔽寄存器
	W5500_RTR0_REG_0x19     	=	0x0019,	//重试时间值寄存器-高字节
	W5500_RTR1_REG_0x1A	    	=	0x001A,	//重试时间值寄存器-低字节
	W5500_RCR_REG_0x1B  		=	0x001B,	//重试计数器
	W5500_PTIMER_REG_0x1C   	=	0x001C,	//PPP连接控制协议请求定时寄存器
	W5500_PMAGIC_REG_0x1D   	=	0x001D,	//PPP连接控制协议幻数寄存器
	W5500_PHAR0_REG_0x1E		=	0x001E,	//PPPoE 模式下目标 MAC 寄存器
	W5500_PHAR1_REG_0x1F		=	0x001F,	//PPPoE 模式下目标 MAC 寄存器
	W5500_PHAR2_REG_0x20		=	0x0020,	//PPPoE 模式下目标 MAC 寄存器
	W5500_PHAR3_REG_0x21		=	0x0021,	//PPPoE 模式下目标 MAC 寄存器
	W5500_PHAR4_REG_0x22		=	0x0022,	//PPPoE 模式下目标 MAC 寄存器
	W5500_PHAR5_REG_0x23		=	0x0023,	//PPPoE 模式下目标 MAC 寄存器
	W5500_PSID0_REG_0x24		=	0x0024,	//PPPoE 模式下会话 ID 寄存器
	W5500_PSID1_REG_0x25		=	0x0025,	//PPPoE 模式下会话 ID 寄存器
	W5500_PMRU0_REG_0x26		=	0x0026,	//PPPoE模式下最大接收单元
	W5500_PMRU1_REG_0x27		=	0x0027,	//PPPoE模式下最大接收单元
	W5500_UIPR0_REG_0x28		=	0x0028,	//无法抵达 IP 地址寄存器
	W5500_UIPR1_REG_0x28		=	0x0029,	//无法抵达 IP 地址寄存器
	W5500_UIPR2_REG_0x2A		=	0x002A,	//无法抵达 IP 地址寄存器
	W5500_UIPR3_REG_0x2B		=	0x002B,	//无法抵达 IP 地址寄存器
	W5500_UPORTR0_REG_0x2C	    =	0x002C,	//无法抵达 端口 地址寄存器
	W5500_UPORTR1_REG_0x2D  	=	0x002D,	//无法抵达 端口 地址寄存器
	W5500_PHYCFGR_REG_0x2E  	=	0x002E,	//W5500 PHY 配置寄 存器
	W5500_VERSIONR_REG_0x39 	=	0x0039,	//芯片版本信息，默认为0x04
}W5500_REG_ADDR;

//socket n寄存器
typedef enum
{
	Sn_MR_0x00			=	0x0000,	//模式寄存器
	Sn_CR_0x01			=	0x0001,	//配置寄存器
	Sn_IR_0x02			=	0X0002,	//中断寄存器
	Sn_SR_0x03			=	0X0003,	//状态寄存器
	Sn_PORT_0x04		=	0X0004,	//源端口寄存器
	Sn_DHAR_0x06		=	0X0006,	//目的MAC地址寄存器
	Sn_DIPR_0x0C		=	0X000C,	//目标IP地址寄存器
	Sn_DPORT_0x10		=	0X0010,	//目标端口寄存器
	Sn_MSSR_0x12		=	0X0012,	//最大分段寄存器
	Sn_TOS_0x15			=	0X0015,	//服务类型寄存器
	Sn_TTL_0x16			=	0X0016,	//生存时间寄存器
	Sn_RXBUFF_SIZE_0x1E	=	0X001E,	//接收缓冲区大小寄存器
	Sn_TXBUFF_SIZE_0x1F	=	0X001F,	//发送缓冲区大小寄存器
	Sn_TX_FSR_0x20		=	0X0020,	//空闲发送缓存寄存器
	Sn_TX_RD_0x22		=	0X0022,	//发送读指针寄存器
	Sn_TX_WR_0x24		=	0X0024,	//发送写指针寄存器
	Sn_RX_RSR_0x26		=	0X0026,	//空闲接收缓存寄存器
	Sn_RX_RD_0x28		=	0X0028,	//接收读指针寄存器
	Sn_RX_WR_0x2A		=	0X002A,	//接收写指针寄存器
	Sn_IMR_0x2C			=	0X002C,	//中断屏蔽寄存器
	Sn_FRAG_0x2D		=	0X002D,	//分段寄存器
	Sn_KPALVTR_0x2F		=	0X002F,	//在线时间寄存器
}W5500_SOCKET_REG;

//SOCKET状态
typedef enum
{
	SOCK_CLOSED		=	0x00,	//关闭状态
	SOCK_INIT		=	0x13,	//初始化
	SOCK_LISTEN		=	0x14,	//监听
	SOCK_ESTABLISHED=	0x17,	//TCP客户端连接成功
	SOCK_CLOSE_WAIT	=	0x1C,	//接收到断开指令
	SOCK_UDP		=	0x22,	//UDP模式下,open
	SOCK_MACRAW		=	0x42,	//MACRAW模式
	SOCK_SYNSENT	=	0x15,	//已经发送连接请求
	SOCK_SYNRECV	=	0x16,	//接收到连接成功指令
	SOCK_FIN_WAIT	=	0x18,	//正在关闭socket
	SOCK_CLOSING 	=	0x1A,	//正在关闭socket
	SOCK_TIME_WAIT	=	0x1B,	//超时关闭socket
	SOCK_LAST_ACK	=	0x1D,	//socket处于关闭状态
}W5500_SOCKET_STATUS;

//socket命令
typedef enum
{
	SOCKET_CMD_OPEN		=	0x01,	//open
	SOCKET_CMD_LISTEN	=	0x02,	//LISTEN
	SOCKET_CMD_CONHECT	=	0x04,	
	SOCKET_CMD_DISCON	=	0x08,
	SOCKET_CMD_CLOSE	=	0x10,
	SOCKET_CMD_SEND		=	0x20,
	SOCKET_CMD_SEND_MAC	=	0x21,
	SOCKET_CMD_SEND_KEEP=	0x22,
	SOCKET_CMD_RECV		=	0x40,
}W5500_SOCKET_CMD;


typedef enum
{
	SOCKET_CLOSED		=	0,
	SOCKET_TCP			=	1,	
	SOCKET_UDP			=	2,
	SOCKET_MACRAW		=	3,
}W5500_PROTOCOL;

typedef void (*W5500RcvCall)(uint8_t socket, uint8_t *buf, uint16_t len);
typedef void (*W5500CloseCall)(uint8_t socket);

typedef struct
{
    uint8_t cs;    
    SpiDev  spi;
    W5500RcvCall rcv_call;
    uint16_t *server_port;
    W5500CloseCall close_call;
    uint8_t close_cnt[W5500_MAX_SOCKET_NUM];
    uint8_t read_buf[W5500_MAX_READ_BUF_SIZE];
}W5500Item;

#define W5500_STATIC_INIT(_name, _spi, _cs, _rcv_call)	\
    W5500Item _name = \
    {   \
		(_cs),	\
		(_spi),	\
        (_rcv_call),	\
    }

void drv_w5500_init(W5500Item *item, uint32_t ip, uint16_t *port_array, uint32_t gateway_ip, uint32_t net_mask, uint8_t *mac, uint16_t timeout);
void drv_w5500_poll(W5500Item *item);
bool drv_w5500_creat_tcp_server(W5500Item *item, uint8_t socket, uint16_t local_port);
    
bool drv_w5500_read_comm_reg(W5500Item *item, uint16_t reg, uint8_t *value, uint16_t len);
bool drv_w5500_write_comm_reg(W5500Item *item, uint8_t reg, uint8_t *value, uint16_t len);
bool drv_w5500_read_socket_reg(W5500Item *item, uint8_t ctrl_phase, uint16_t reg, uint8_t *value, uint16_t len);
bool drv_w5500_write_socket_reg(W5500Item *item, uint8_t ctrl_phase, uint16_t reg, uint8_t *value, uint16_t len);
bool drv_w5500_dma_write_socket_reg(W5500Item *item, uint8_t ctrl_phase, uint16_t reg, uint8_t *value, uint16_t len);
bool drv_w5500_dma_read_socket_reg(W5500Item *item, uint8_t ctrl_phase, uint16_t reg, uint8_t *value, uint16_t len);
    
uint8_t drv_w5500_get_socket_status(W5500Item *item, uint8_t socket);
bool drv_w5500_close_socket(W5500Item *item, uint8_t socket);
void drv_w5500_set_close_call(W5500Item *item, W5500CloseCall call);    

#endif
