
#include "YGV642_SPI_Flash_IS25LP256D.h"

/*------------------------------------------------------------------------------*/
/* Function name    : PM_IS25LP256D_ID_Check                                     */
/* Contents         : Pattern Memory JEDEC ID check                             */
/* Argument         : void                                                      */
/* Return value     : 1 - Pass 0 - Fail                                         */
/*------------------------------------------------------------------------------*/
uint8_t PM_IS25LP256D_ID_Check(void)
{
  uint8_t   i;
  uint8_t   Identifier[3];

  /* (1), (2) Write Pattern Memory Control register */
	PM_IS25LP256D_Write_Cmd(PM_IS25LP256D_CMD_READ_JEDEC_ID, 7, 0);

	/* (3) Write R#27h: AIPM = 1 */
	YGV642_Write_Reg(REG_R27H, 0x07);

	/* (4) Write P#2: CSNEG = 1 */
	YGV642_Write_Port(YVC1_PORT_PTNMEM_READACS, PM_IS25LP256D_READACS_CSNEG);

	/* (5) Write R#2C-R#2F: PMA[25:0] */
	PM_IS25LP256D_Set_Pattern_Memory_Addr(0x00000000UL);
  
  for (i = 0; i < 3; i++)
  {
    /* Read request */
    YGV642_Write_Port(YVC1_PORT_PTNMEM_READACS, PM_IS25LP256D_READACS_PMRREQ);

    /* Waiting for ready to read */
    PM_IS25LP256D_Wait_Clear_Flag(PM_IS25LP256D_READACS_PMRREQ | PM_IS25LP256D_READACS_PWBUSY);

    /* Read register value */
    Identifier[i] = YGV642_Read_Port(YVC1_PORT_PTNMEM_DATA);
  }
  
  if ((Identifier[0] == PM_IS25LP256D_MANUFACTURER_ID) &&\
      (Identifier[1] == PM_IS25LP256D_DEVICE_ID_MSB  ) &&\
      (Identifier[2] == PM_IS25LP256D_DEVICE_ID_LSB  ))
    return 1;
    
  return 0;
}

/*------------------------------------------------------------------------------*/
/* Function name    : PM_IS25LP256D_Init                                         */
/* Contents         : Initialize Pattern Memory                                 */
/* Argument         : void                                                      */
/* Return value     : void                                                      */
/*------------------------------------------------------------------------------*/
void PM_IS25LP256D_Init(void)
{
  uint8_t   ReadData;
  uint32_t  Cnt;
  
  /* Set CSNEG */
	YGV642_Write_Port(Y642_PORT_PTNMEM_READACS, PM_IS25LP256D_READACS_CSNEG);
  
  /* Set & send Write Enable command */
	PM_IS25LP256D_Write_Cmd(PM_IS25LP256D_CMD_E_WRITE_ENABLE, 5, 1);
	PM_IS25LP256D_Wait_Clear_Flag(PM_IS25LP256D_READACS_PWBUSY); 
  
	/* Set & send Write Enhanced Volatile Configuration command, enter Quod mode */
	PM_IS25LP256D_Write_Cmd(PM_IS25LP256D_CMD_E_WRITE_STATUS, 7, 1);
  PM_IS25LP256D_Wait_Clear_Flag(PM_IS25LP256D_READACS_PWBUSY); 
  
	/* Read enhanced volatile configuration register */
  Cnt = 0;
	do
  {
    ReadData = PM_IS25LP256D_Read_Pattern_Memory_Data_Port(PM_IS25LP256D_CMD_E_READ_STATUS, 5);
    Cnt++;
	}
  while(((ReadData & PM_IS25LP256D_READ_REGISTER_MASK) != 0) && (Cnt < PM_IS25LP256D_POLLING_COUNT_MAX));
  
	/* Enter 4 byte mode */
	/* Set CSNEG */
	YGV642_Write_Port(Y642_PORT_PTNMEM_READACS, PM_IS25LP256D_READACS_CSNEG);

	/* Set & send Write Enable command */
  PM_IS25LP256D_Write_Cmd(PM_IS25LP256D_CMD_ENTER_4_BYTE_ADDRESS_MODE, 5, 1);
	PM_IS25LP256D_Wait_Clear_Flag(PM_IS25LP256D_READACS_PWBUSY); 
  
  ReadData = PM_IS25LP256D_Read_Pattern_Memory_Data_Port(PM_IS25LP256D_CMD_E_READ_CONFIG, 5);
  
	/*set pattern address*/
  PM_IS25LP256D_Set_Pattern_Memory_Addr(0x00000000UL);
  
	/*Enter continuous Quad Input/Output Fast Read */
  ReadData = PM_IS25LP256D_Read_Pattern_Memory_Data_Port(PM_IS25LP256D_CMD_QUAD_INPUT_OUTPUT_FAST_CONTINUOUS_READ_ENTER,7);
  
	/* CSNEG = 0 */
	YGV642_Write_Port(Y642_PORT_PTNMEM_READACS, 0);
  
	/* Set continuous Quad Input/Output Fast Read command */
  YGV642_Write_Regs(REG_R55H, PMIS25LP256DCmdData[PM_IS25LP256D_CMD_QUAD_INPUT_OUTPUT_FAST_CONTINUOUS_READ], 7);
}

/*------------------------------------------------------------------------------*/
/* Function name    : PM_IS25LP256D_Set_Pattern_Memory_Addr                      */
/* Contents         : Set Pattern Memory Address register                       */
/* Argument         : uint32_t   Addr     (W) Pattern Memory Address            */
/* Return value     : void                                                      */
/*------------------------------------------------------------------------------*/  
void PM_IS25LP256D_Set_Pattern_Memory_Addr(uint32_t Addr)
{
	uint8_t MemAddr[4];
	
	/*---	Pattern memory address set	---*/
	MemAddr[0] = (uint8_t)(( Addr >> SHIFT_24BIT ) & MASK_03H);
	MemAddr[1] = (uint8_t)(( Addr >> SHIFT_16BIT ) & MASK_FFH);
	MemAddr[2] = (uint8_t)(( Addr >> SHIFT_08BIT ) & MASK_FFH);
	MemAddr[3] = (uint8_t)(( Addr                ) & MASK_FFH);

  YGV642_Write_Regs(REG_R2CH, MemAddr, 4);
}

/*------------------------------------------------------------------------------*/
/* Function name    : PM_IS25LP256D_Write_Cmd                                    */
/* Contents         : Write Pattern Memory Control registers                    */
/* Argument         : uint8_t   CmdNo    (W) Command No                         */
/* Return value     : void                                                      */
/*------------------------------------------------------------------------------*/
void PM_IS25LP256D_Write_Cmd(uint8_t CmdNo, uint8_t CmdLen, uint8_t Send)
{
  /*	Access Port	
	 *
	 *	 No.   Description 		 						  bit7   bit6   bit5   bit4   bit3   bit2   bit1   bit0 
	 *	+---+-------------------------------------------+------+------+------+------+------+------+------+------+
	 *	| 2 | Pattern Memory Read Access Port / Status 	|PMRREQ|PWBUSY|INIEND|CSNEG | "0"  | "0"  | "0"  | "0"  |
	 *	+---+-------------------------------------------+------+------+------+------+------+------+------+------+
	 *	| 3 | Pattern Memory Data Port 					|                        MD[7:0]                        |
	 *	+---+-------------------------------------------+------+------+------+------+------+------+------+------+
	 */
   

	/* Waiting for ready to write */
	PM_IS25LP256D_Wait_Clear_Flag(PM_IS25LP256D_READACS_PMRREQ | PM_IS25LP256D_READACS_PWBUSY);
  
 	/* Set command to R#55h-#5Bh */
  YGV642_Write_Regs(0x55, PMIS25LP256DCmdData[CmdNo], CmdLen); 
  
  /* Send command */
  if (Send)
    YGV642_Write_Port(Y642_PORT_PTNMEM_DATA, PMIS25LP256DCmdData[CmdNo][7]);
}

/*------------------------------------------------------------------------------*/
/* Function name    : YGV642_Read_Pattern_Memory_Data_Port                      */
/* Contents         : Read Pattern Memory Data Port                             */
/*                  : uint8_t *Data    (R) Data pointer                         */
/* Argument         : void                                                      */
/* Return value     : void                                                      */
/*------------------------------------------------------------------------------*/
uint8_t PM_IS25LP256D_Read_Pattern_Memory_Data_Port(uint8_t CmdNo, uint8_t CmdLen)
{
  uint8_t Data;
  
  /* Set Command */
  PM_IS25LP256D_Write_Cmd(CmdNo, CmdLen, 0);
  
	/* Read request */
	YGV642_Write_Port(YVC1_PORT_PTNMEM_READACS, PM_IS25LP256D_READACS_PMRREQ | PM_IS25LP256D_READACS_CSNEG);

	/* Waiting for ready to read */
	PM_IS25LP256D_Wait_Clear_Flag(PM_IS25LP256D_READACS_PMRREQ | PM_IS25LP256D_READACS_PWBUSY);

	/* Read register value */
	Data = YGV642_Read_Port(YVC1_PORT_PTNMEM_DATA);
  
  return Data;
}

/*------------------------------------------------------------------------------*/
/* Function name    : PM_IS25LP256D_Wait_Clear_Flag                              */
/* Contents         : Wait to clear flags                                       */
/* Argument         : uint8_t   Mask    (W) Mask value                          */
/* Return value     : void                                                      */
/*------------------------------------------------------------------------------*/ 
void PM_IS25LP256D_Wait_Clear_Flag(uint8_t Mask)
{
  uint8_t   ReadData;
  uint32_t  Cnt;

  Cnt = 0;
  do
  {
    ReadData = YGV642_Read_Port(YVC1_PORT_PTNMEM_READACS);
    Cnt++;
  }
  while (((ReadData & Mask) != 0) && (Cnt < PM_IS25LP256D_POLLING_COUNT_MAX));
}
