
#ifndef __IC_APS1604M_H__
#define __IC_APS1604M_H__

#include "stdint.h"
#include "stdbool.h"

#include "fxx_spi.h"
#include "fxx_gpio.h" 

#define PSRAM __attribute__((section("PSRAM")))

typedef enum
{
    ERR_PSRAM_NONE = 0,
    ERR_PSRAM_DMANOTCFGED,
    ERR_PSRAM_PARAM,
}HAL_SPI_PSRAM_Status;

typedef enum
{
    PSRAM_SPI_MODE,
    PSRAM_QPI_MODE
}psram_mode_enum;

typedef enum
{
    SPI_CS_HW = 0,
    SPI_CS_SW = 1,    
}spi_cs_mode_enum;

typedef struct _psram_info
{
    SPI_TypeDef *SPIx;     /* SPI handle for PSRAM interface */
    uint32_t psram_state;       /* PSRAM POR, RESET state, etc */
    psram_mode_enum mode;       /* PSRAM is currently in spi mode or in qpi mode */
}psram_info_t;

#define APS1604M_CMD_RD							0x03
#define APS1604M_CMD_FAST_RD					0x0B
#define APS1604M_CMD_WRAP_RD					0x8B	//wrapped read
#define APS1604M_CMD_FAST_QRD					0xEB	//fast quad read
#define APS1604M_CMD_WR							0x02
#define APS1604M_CMD_WRAP_WR					0x8B	//wrapped write
#define APS1604M_CMD_QWR						0x38	//quad write
#define APS1604M_CMD_MOD_REG_RD					0xB5	//mode register read
#define APS1604M_CMD_MOD_REG_WR					0xB1	//mode register write
#define APS1604M_CMD_ENTER_QPI_MODE				0x35	//enter quad mode
#define APS1604M_CMD_EXIT_QPI_MODE			    0xF5	//exit quad mode
#define APS1604M_CMD_RST_EN						0x66	//reset enable
#define APS1604M_CMD_RST						0x99	//reset
#define APS1604M_CMD_BUR_LEN_TOG				0xC0	//burst length toggle
#define APS1604M_CMD_RD_ID						0x9F	//read ID



/* paltform dependent */
#define SPI_PSRAM_DMA_REQ_TX                    (REQ47_SPI3_SEND)
#define SPI_PSRAM_DMA_REQ_RX                    (REQ48_SPI3_RECV)
/* paltform dependent */
#define SPI_PSRAM_CS_PORT						GPIOD
#define SPI_PSRAM_CS_PIN						GPIO_PIN_13

#define SPI_PSRAM_CS_H()						GPIO_WriteBit(SPI_PSRAM_CS_PORT, SPI_PSRAM_CS_PIN, Bit_SET)
#define SPI_PSRAM_CS_L()						GPIO_WriteBit(SPI_PSRAM_CS_PORT, SPI_PSRAM_CS_PIN, Bit_RESET)


#define SPI_PSRAM_DMA_DISABLE()                 psram_info.SPIx->RX_CTL &= ~(SPI_RX_CTL_DMA_REQ_EN | SPI_TX_CTL_DMA_REQ_EN)

#define __SPI_PSRAM_Read_Data(buf, size)        SPI_Receive(buf, size, 0)

#define __SPI_PSRAM_Write_Data(buf, size)       SPI_Transmit(buf, size, 0)

#define __SPI_PSRAM_SET_1X_MODE()               SPI_Wire_Config(psram_info.SPIx, SPI_1X_MODE)
#define __SPI_PSRAM_SET_2X_MODE()               SPI_Wire_Config(psram_info.SPIx, SPI_2X_MODE)
#define __SPI_PSRAM_SET_4X_MODE()               SPI_Wire_Config(psram_info.SPIx, SPI_4X_MODE)

#define __SWITCH_TO_FIFO_MODE()                 { SPI3->MEMO_ACC &= ~SPI_ACC_EN; SPI_CS_Mode_Cfg(SPI_CS_SW); }
#define __SWITCH_TO_XIP_MODE()                  { __SPI_PSRAM_SET_1X_MODE(); SPI_CS_Mode_Cfg(SPI_CS_HW); SPI_PSRAM_DMA_DISABLE(); SPI3->MEMO_ACC |= SPI_ACC_EN; }



//psram_info_t * get_psram_info(void);

HAL_SPI_PSRAM_Status IC_APS1604M_Init(SPI_TypeDef* SPIx, DMA_Channel_TypeDef *dma_rx_ch, DMA_Channel_TypeDef *dma_tx_ch);

uint16_t IC_APS1604M_Read_ID(uint8_t eid[6]);

HAL_SPI_PSRAM_Status IC_APS1604M_Reset(void);
HAL_SPI_PSRAM_Status IC_APS1604M_Enter_QPI_Mode(void);
HAL_SPI_PSRAM_Status IC_APS1604M_Exit_QPI_Mode(void);

HAL_SPI_PSRAM_Status IC_APS1604M_Read(uint32_t addr, void *buf,  uint32_t len);
HAL_SPI_PSRAM_Status IC_APS1604M_Write(uint32_t addr, void *buf,  uint32_t len);

HAL_SPI_PSRAM_Status IC_APS1604M_QPI_Read(uint32_t addr, void *buf,  uint32_t len);
HAL_SPI_PSRAM_Status IC_APS1604M_QPI_Write(uint32_t addr, void *buf,  uint32_t len);

void IC_APS1604M_DMA_RW_Cfg(DMA_Channel_TypeDef *dma_rx_ch, DMA_Channel_TypeDef *dma_tx_ch);

HAL_SPI_PSRAM_Status IC_APS1604M_DMA_Read(uint32_t addr, void *buf,  uint32_t len);
HAL_SPI_PSRAM_Status IC_APS1604M_DMA_Write(uint32_t addr, void *buf,  uint32_t len);

HAL_SPI_PSRAM_Status IC_APS1604M_QPI_DMA_Read(uint32_t addr, void *buf,  uint32_t len);
HAL_SPI_PSRAM_Status IC_APS1604M_QPI_DMA_Write(uint32_t addr, void *buf,  uint32_t len);

#endif

