This application provides a set of demos with X-NUCLEO-NFC01A1 expansion board.

Dependencies:   NDefLib X_NUCLEO_NFC01A1 mbed

Fork of X-MBED-NFC1 by Giovanni Visentini

This application provides a set of demos with X-NUCLEO-NFC01A1 expansion board.

The available demos are:

  • SAMPLE_WRITE_URL: write a tag with the ST home page URL
  • SAMPLE_COUNT_CLICK: create a custom tag to count and report the user button clicks.
  • SAMPLE_WRITE_AND_CHANGE_ALL: write a tag with all the supported records and update the tag contents when the user button is pressed.
  • SAMPLE_LOCK_TAG_CONTENT: use the M24SR component API to set the NFC tag as read-only.

To enable the different demos comment/uncomment the SAMPLE_* macros provided in main.cpp .

m24sr/m24sr_class.cpp

Committer:
giovannivisentini
Date:
2015-11-19
Revision:
0:674813bd5ec9
Child:
1:6d202b62ed68

File content as of revision 0:674813bd5ec9:

/**
  ******************************************************************************
  * @file    m24sr_class.cpp
  * @author  MMY Application Team
  * @version V1.2.0
  * @date    20-October-2014
  * @brief   This file provides a set of functions to interface with the M24SR
  *          device.
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; COPYRIGHT(c) 2014 STMicroelectronics</center></h2>
  *
  * Redistribution and use in source and binary forms, with or without modification,
  * are permitted provided that the following conditions are met:
  *   1. Redistributions of source code must retain the above copyright notice,
  *      this list of conditions and the following disclaimer.
  *   2. Redistributions in binary form must reproduce the above copyright notice,
  *      this list of conditions and the following disclaimer in the documentation
  *      and/or other materials provided with the distribution.
  *   3. Neither the name of STMicroelectronics nor the names of its contributors
  *      may be used to endorse or promote products derived from this software
  *      without specific prior written permission.
  *
  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  ******************************************************************************
  */


/* Generated with Stm32CubeTOO -----------------------------------------------*/


/* Revision ------------------------------------------------------------------*/
/*
	Repository:       http://svn.x-nucleodev.codex.cro.st.com/svnroot/X-NucleoDev
	Branch/Trunk/Tag: trunk
	Based on:         X-CUBE-MEMS1/trunk/Drivers/BSP/Components/m24sr/m24sr.c
	Revision:         :410
*/

/* Includes ------------------------------------------------------------------*/
#include "m24sr_class.h"
#include "m24sr.h"

/** @addtogroup M24SR_Driver
  * @{
  *	@brief  <b>This folder contains the driver layer of M24SR family (M24SR64, M24SR16, M24SR04, M24SR02)</b> 
  */


/** @defgroup drv_M24SR
  * @{
	*	@brief  This file contains the driver which implements all the M24SR commands.
  */

#ifndef errchk
#define errchk(fCall) if (status = (fCall), status != NFC_IO_SUCCESS) \
	{goto Error;} else
#endif


/**
  * @brief  This function updates the CRC 
  * @param  None
  * @retval None
  */
uint16_t M24SR_UpdateCrc (uint8_t ch, uint16_t *lpwCrc)
{
  ch = (ch^(uint8_t)((*lpwCrc) & 0x00FF));
  ch = (ch^(ch<<4));
  *lpwCrc = (*lpwCrc >> 8)^((uint16_t)ch << 8)^((uint16_t)ch<<3)^((uint16_t)ch>>4);
	
  return (*lpwCrc);
}

/**
  * @brief  This function returns the CRC 16 
  * @param  Data : pointer on the data used to compute the CRC16
  * @param  Length : number of byte of the data
  * @retval CRC16 
  */
uint16_t M24SR_ComputeCrc(uint8_t *Data, uint8_t Length)
{
  uint8_t chBlock;
  uint16_t wCrc = 0x6363; // ITU-V.41
  
  do {
    chBlock = *Data++;
    M24SR_UpdateCrc(chBlock, &wCrc);
  } while (--Length);
  
  return wCrc ;
}


/**  
* @brief  	This function computes the CRC16 residue as defined by CRC ISO/IEC 13239
* @param  	DataIn		:	input to data 
* @param		Length 		: 	Number of bits of DataIn
* @retval 	Status (SW1&SW2)  	:   CRC16 residue is correct	
* @retval 	M24SR_ERROR_CRC  	:  CRC16 residue is false
*/
NFC_StatusTypeDef M24SR_IsCorrectCRC16Residue (uint8_t *DataIn,uint8_t Length)
{
  uint16_t ResCRC=0x0000;
  
	/* check the CRC16 Residue */
	if (Length !=0)
		ResCRC= M24SR_ComputeCrc (DataIn, Length);
	
	if ( ResCRC == 0x0000)
	{
		/* Good CRC, but error status from M24SR */
    return(NFC_StatusTypeDef)(((DataIn[Length-UB_STATUS_OFFSET]<<8) & 0xFF00) | (DataIn[Length-LB_STATUS_OFFSET] & 0x00FF) );
	}
	else
	{
		ResCRC=0x0000;
		ResCRC= M24SR_ComputeCrc (DataIn, 5);
		if ( ResCRC != 0x0000)
		{
			/* Bad CRC */
			return NFC_IO_ERROR_CRC;
		}
		else
		{
			/* Good CRC, but error status from M24SR */
			return (NFC_StatusTypeDef)( ((DataIn[1]<<8) & 0xFF00) | (DataIn[2] & 0x00FF) );
		}
	}	
}

/**
  * @brief  Initialize the command and response structure 
  * @param  None
  * @retval None
  */
void M24SR::M24SR_InitCommandStructure ( void )
{

	/* build the command */
	command.Header.CLA = 0x00;
	command.Header.INS = 0x00;
	/* copy the offset */
	command.Header.P1 = 0x00 ;
	command.Header.P2 = 0x00 ;
	/* copy the number of byte of the data field */
	command.Body.LC = 0x00 ;
	/* copy the number of byte to read */
	command.Body.LE = 0x00 ;
	command.Body.pData = dataBuffer;
	
  // 	/* initializes the response structure*/
  // 	Response.pData = contex->DataBuffer;
  // 	Response.SW1 = 0x00;
  // 	Response.SW2 = 0x00;
}

/**
  * @brief 		This functions creates an I block command according to the structures CommandStructure and data->command.
	* @param	 	Command : structue which contains the field of the different parameter
	* @param	 	CommandStructure : structure that contain the structure of the command (if the different field are presnet or not 
	* @param	 	NbByte : number of byte of the command
	* @param	 	pCommand : pointer of the command created
  */
void M24SR_BuildIBlockCommand (uint16_t CommandStructure,C_APDU *Command,uint8_t uDIDbyte, uint16_t *NbByte , uint8_t *pCommand)
{
	uint16_t	uCRC16;
	static uint8_t BlockNumber = 0x01;
	
	(*NbByte) = 0;
	
	/* add the PCD byte */
	if ((CommandStructure & M24SR_PCB_NEEDED) !=0)
	{
		/* toggle the block number */
		BlockNumber = TOGGLE ( BlockNumber );
		/* Add the I block byte */
		pCommand[(*NbByte)++] = 0x02 |  BlockNumber; 
	}
	
	/* add the DID byte */
	if ((BlockNumber & M24SR_DID_NEEDED) !=0)
	{
		/* Add the I block byte */
		pCommand[(*NbByte)++] = uDIDbyte;
	}
	
	/* add the Class byte */
	if ((CommandStructure & M24SR_CLA_NEEDED) !=0)
	{
		pCommand[(*NbByte)++] = Command->Header.CLA ;
	}
	/* add the instruction byte byte */
	if ( (CommandStructure & M24SR_INS_NEEDED) !=0)
	{
		pCommand[(*NbByte)++] = Command->Header.INS ;
	}
	/* add the Selection Mode byte */
	if ((CommandStructure & M24SR_P1_NEEDED) !=0)
	{
		pCommand[(*NbByte)++] = Command->Header.P1 ;
	}
	/* add the Selection Mode byte */
	if ((CommandStructure & M24SR_P2_NEEDED) !=0)
	{
		pCommand[(*NbByte)++] = Command->Header.P2 ;
	}
	/* add Data field lengthbyte */
	if ((CommandStructure & M24SR_LC_NEEDED) !=0)
	{
		pCommand[(*NbByte)++] = Command->Body.LC ;
	}
	/* add Data field  */
	if ((CommandStructure & M24SR_DATA_NEEDED) !=0)
	{
		memcpy(&(pCommand[(*NbByte)]) ,Command->Body.pData,Command->Body.LC ) ;
		(*NbByte) += Command->Body.LC ;
	}
	/* add Le field  */
	if ((CommandStructure & M24SR_LE_NEEDED) !=0)
	{
		pCommand[(*NbByte)++] = Command->Body.LE ;
	}
	/* add CRC field  */
	if ((CommandStructure & M24SR_CRC_NEEDED) !=0)
	{
		uCRC16 = M24SR_ComputeCrc (pCommand,(uint8_t) (*NbByte));
		/* append the CRC16 */
		pCommand [(*NbByte)++] = GETLSB	(uCRC16 ) ;
		pCommand [(*NbByte)++] = GETMSB	(uCRC16 ) ;	
	}
  
}

#if 0
/**  
* @brief  	This function return M24SR_STATUS_SUCCESS if the pBuffer is an I-block
* @param  	pBuffer		:	pointer of the data
* @retval 	M24SR_STATUS_SUCCESS  :  the data is a I-Block
* @retval 	M24SR_ERROR_DEFAULT  	:  the data is not a I-Block
*/
static int8_t IsIBlock (uint8_t *pBuffer)
{
  
	if ((pBuffer[M24SR_OFFSET_PCB] & M24SR_MASK_BLOCK) == M24SR_MASK_IBLOCK)
	{
		return M24SR_STATUS_SUCCESS;
	}
	else 
	{	
		return M24SR_ERROR_DEFAULT;
	}
	
}

/**  
* @brief  	This function return M24SR_STATUS_SUCCESS if the pBuffer is an R-block
* @param  	pBuffer		:	pointer of the data
* @retval 	M24SR_STATUS_SUCCESS  :  the data is a R-Block
* @retval 	M24SR_ERROR_DEFAULT  	:  the data is not a R-Block
*/
static int8_t IsRBlock (uint8_t *pBuffer)
{
  
	if ((pBuffer[M24SR_OFFSET_PCB] & M24SR_MASK_BLOCK) == M24SR_MASK_RBLOCK)
	{
		return M24SR_STATUS_SUCCESS;
	}
	else 
	{	
		return M24SR_ERROR_DEFAULT;
	}
	
}
#endif	
	
/**  
* @brief  	This function return M24SR_STATUS_SUCCESS if the pBuffer is an s-block
* @param  	pBuffer		:	pointer of the data
* @retval 	M24SR_STATUS_SUCCESS  :  the data is a S-Block
* @retval 	M24SR_ERROR_DEFAULT  	:  the data is not a S-Block
*/
static int8_t IsSBlock (uint8_t *pBuffer)
{
  
	if ((pBuffer[M24SR_OFFSET_PCB] & M24SR_MASK_BLOCK) == M24SR_MASK_SBLOCK)
	{
		return NFC_IO_SUCCESS;
	}
	else 
	{	
		return NFC_IO_ERROR_DEFAULT;
	}
	
}

/**
  * @brief  This function sends the FWT extension command (S-Block format)
	* @param	FWTbyte : FWT value
  * @retval Status (SW1&SW2) : Status of the operation to complete.
	* @retval M24SR_ERROR_I2CTIMEOUT : The I2C timeout occured.
  */
NFC_StatusTypeDef M24SR::M24SR_FWTExtension (uint8_t FWTbyte )
{
  uint8_t 	pBuffer[M24SR_STATUSRESPONSE_NBBYTE];
  NFC_StatusTypeDef		status ;
  uint8_t	NthByte = 0;
  uint16_t uCRC16;
  
	/* create the response */
	pBuffer[NthByte++] = 0xF2 ;	
	pBuffer[NthByte++] = FWTbyte ;
	/* compute the CRC */
	uCRC16 = M24SR_ComputeCrc (pBuffer,0x02);
	/* append the CRC16 */
	pBuffer [NthByte++] = GETLSB	(uCRC16 ) ;
	pBuffer [NthByte++]=  GETMSB	(uCRC16 ) ;
	
	/* send the request */ 
	errchk( M24SR_IO_SendI2Ccommand (NthByte , pBuffer ));
	errchk( M24SR_IO_IsAnswerReady ());
	/* read the response */ 
	errchk( M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , pBuffer ));
	
	status = M24SR_IsCorrectCRC16Residue (pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
	return status;
	
Error :
	return NFC_IO_ERROR_I2CTIMEOUT;
}

/**
  * @brief  This function sends the KillSession command to the M24SR device
  * @param  None
	* @retval NFC_OK : the function is succesful.
	* @retval M24SR_ERROR_I2CTIMEOUT : The I2C timeout occured.
  */
NFC_StatusTypeDef M24SR::M24SR_KillSession ( void )
{
	uint8_t commandBuffer[] = M24SR_KILLSESSION_COMMAND;
	int8_t 	status;

	errchk(M24SR_IO_SendI2Ccommand (sizeof(commandBuffer) , commandBuffer ));

	/* Insure no access will be done just after open session */
	/* The only way here is to poll I2C to know when M24SR is ready */
	/* GPO can not be use with KillSession command */
	errchk(M24SR_IO_PollI2C ());

	return NFC_OK;
Error :
	return NFC_IO_ERROR_I2CTIMEOUT;
}


/**
  * @brief  This function sends the Deselect command (S-Block format)
	* @retval NFC_OK : the function is succesful.
	* @retval M24SR_ERROR_I2CTIMEOUT : The I2C timeout occured.
  */
NFC_StatusTypeDef M24SR::M24SR_Deselect ( void )
{
	uint8_t 	pBuffer[] = M24SR_DESELECTREQUEST_COMMAND ;
	int8_t		status ;

	/* send the request */
	errchk( M24SR_IO_SendI2Ccommand (sizeof(pBuffer) , pBuffer ));

	errchk( M24SR_IO_IsAnswerReady ());
	/* flush the M24SR buffer */
	errchk( M24SR_IO_ReceiveI2Cresponse (sizeof(pBuffer) , pBuffer ));

	return NFC_OK;

Error :
	return NFC_IO_ERROR_I2CTIMEOUT;
}




/**
  * @brief  This function sends the SelectApplication command
	* @retval NFC_OK : the function is succesful.
	* @retval M24SR_ERROR_I2CTIMEOUT : The I2C timeout occured.
  */
NFC_StatusTypeDef M24SR::M24SR_SelectApplication ( void )
{

	C_APDU command;
	uint8_t 	*pBuffer = uM24SRbuffer;
	uint8_t pDataIn[M24SR_STATUSRESPONSE_NBBYTE];
	uint8_t pDataOut[] = M24SR_SELECTAPPLICATION_COMMAND;
	uint8_t uLe = 0x00;
	NFC_StatusTypeDef	status ;
	uint16_t	uP1P2 =0x0400,  NbByte;
	
	/* build the command */
	command.Header.CLA = C_APDU_CLA_DEFAULT;
	command.Header.INS = C_APDU_SELECT_FILE;
	/* copy the offset */
	command.Header.P1 = GETMSB	(uP1P2 ) ;
	command.Header.P2 = GETLSB	(uP1P2 ) ;
	/* copy the number of byte of the data field */
	command.Body.LC = sizeof(pDataOut) ;
	/* copy the data */
	command.Body.pData=pDataOut;
	/* copy the number of byte to read */
	command.Body.LE = uLe ;
	/* build the I²C command */
	M24SR_BuildIBlockCommand ( M24SR_CMDSTRUCT_SELECTAPPLICATION,  &command,uDIDbyte, &NbByte , pBuffer);
	
	/* send the request */ 
	errchk( M24SR_IO_SendI2Ccommand (NbByte , pBuffer ));
	errchk( M24SR_IO_IsAnswerReady ());
	/* read the response */ 
	errchk( M24SR_IO_ReceiveI2Cresponse (sizeof(pDataIn) , pDataIn ));
	
	status = M24SR_IsCorrectCRC16Residue (pDataIn,sizeof(pDataIn));
	return status;
	
Error :
	return NFC_IO_ERROR_I2CTIMEOUT;
}


/**
  * @brief  This function initialize the M24SR device
  * @retval None
  */
NFC_StatusTypeDef M24SR::M24SR_Init(NFC_InitTypeDef *notUsed)
{
	(void)notUsed;

	M24SR_InitCommandStructure();

/*
	if( M24SR_KillSession() == NFC_OK)
	{
		M24SR_ManageI2CGPO(I2C_ANSWER_READY);
	  M24SR_Deselect ();
	}
*/
	return NFC_OK;
}

NFC_StatusTypeDef M24SR::M24SR_ReadID(uint8_t *nfc_id){
	 if(!nfc_id){
	    return NFC_ERROR;
	  }
	NFC_StatusTypeDef error = M24SR_SelectApplication();
	if(error!=NFC_IO_SUCCESS)
		return error;

	return M24SR_ReadBinary(0x0011,1,nfc_id);
}


/**
  * @brief  This function sends the GetSession command to the M24SR device
	* @retval NFC_OK : the function is succesful.
  * @retval Status (SW1&SW2) : if operation does not complete.
  */
NFC_StatusTypeDef M24SR::M24SR_GetSession ( void )
{
	uint8_t commandBuffer[] = M24SR_OPENSESSION_COMMAND;
	int16_t 	status;

	errchk(M24SR_IO_SendI2Ccommand (sizeof(commandBuffer) , commandBuffer ));

	/* Insure no access will be done just after open session */
	/* The only way here is to poll I2C to know when M24SR is ready */
	/* GPO can not be use with GetSession command */
	errchk(M24SR_IO_PollI2C ());

	return NFC_OK;
Error :
	return NFC_IO_ERROR_I2CTIMEOUT;
}




/**
  * @brief  This function sends the SelectCCFile command
	* @retval NFC_OK : the function is succesful.
	* @retval M24SR_ERROR_I2CTIMEOUT : The I2C timeout occured.
  * @retval Status (SW1&SW2) : if operation does not complete for another reason.
  */
NFC_StatusTypeDef M24SR::M24SR_SelectCCfile ( void )
{
	C_APDU command;

	uint8_t *pBuffer = uM24SRbuffer;
	uint8_t pDataIn[M24SR_STATUSRESPONSE_NBBYTE];
	uint8_t pDataOut[] = CC_FILE_ID_BYTES;
	NFC_StatusTypeDef status;
	uint16_t uP1P2 =0x000C,	NbByte;

	/* build the command */
	command.Header.CLA = C_APDU_CLA_DEFAULT;
	command.Header.INS = C_APDU_SELECT_FILE;
	/* copy the offset */
	command.Header.P1 = GETMSB(uP1P2);
	command.Header.P2 = GETLSB(uP1P2);
	/* copy the number of byte of the data field */
	command.Body.LC = sizeof(pDataOut);
	command.Body.pData = pDataOut;
	/* build the I²C command */
	M24SR_BuildIBlockCommand(M24SR_CMDSTRUCT_SELECTCCFILE, &command, uDIDbyte,
			&NbByte, pBuffer);

	/* send the request */
	errchk(M24SR_IO_SendI2Ccommand(NbByte, pBuffer));
	errchk(M24SR_IO_IsAnswerReady());
	/* read the response */
	errchk(M24SR_IO_ReceiveI2Cresponse(sizeof(pDataIn), pDataIn));

	status = M24SR_IsCorrectCRC16Residue(pDataIn, sizeof(pDataIn));
	return status;

	Error:
		return NFC_IO_ERROR_I2CTIMEOUT;
}


/**
  * @brief  This function sends the SelectSystemFile command
  * @retval Status (SW1&SW2) : Status of the operation to complete.
	* @retval M24SR_ERROR_I2CTIMEOUT : The I2C timeout occured.
  */
NFC_StatusTypeDef M24SR::M24SR_SelectSystemfile ( void )
{
	C_APDU command;

	uint8_t 	*pBuffer = uM24SRbuffer;
	uint8_t pDataIn[M24SR_STATUSRESPONSE_NBBYTE];
	uint8_t pDataOut[] = SYSTEM_FILE_ID_BYTES;
  NFC_StatusTypeDef	status ;
  uint16_t	uP1P2 =0x000C, NbByte;
	
	/* build the command */
	command.Header.CLA = C_APDU_CLA_DEFAULT;
	command.Header.INS = C_APDU_SELECT_FILE;
	/* copy the offset */
	command.Header.P1 = GETMSB	(uP1P2 ) ;
	command.Header.P2 = GETLSB	(uP1P2 ) ;
	/* copy the number of byte of the data field */
	command.Body.LC = sizeof(pDataOut);
	command.Body.pData=pDataOut;
	/* build the I²C command */
	M24SR_BuildIBlockCommand (M24SR_CMDSTRUCT_SELECTCCFILE,  &command,uDIDbyte, &NbByte , pBuffer);
	
	/* send the request */ 
	errchk( M24SR_IO_SendI2Ccommand (NbByte , pBuffer ));
	errchk( M24SR_IO_IsAnswerReady ());
	/* read the response */ 
	errchk( M24SR_IO_ReceiveI2Cresponse (sizeof(pDataIn) , pDataIn ));
	
	status = M24SR_IsCorrectCRC16Residue (pDataIn,sizeof(pDataIn));
	return status;
  
Error :
	return NFC_IO_ERROR_I2CTIMEOUT;
}

/**
  * @brief  This function sends the SelectNDEFfile command
  * @retval Status (SW1&SW2) : Status of the operation to complete.
	* @retval M24SR_ERROR_I2CTIMEOUT : The I2C timeout occured.
  */
NFC_StatusTypeDef M24SR::M24SR_SelectNDEFfile (uint16_t NDEFfileId )
{
	C_APDU command;
	uint8_t 	*pBuffer = uM24SRbuffer;
	uint8_t pDataIn[M24SR_STATUSRESPONSE_NBBYTE];
	uint8_t pDataOut[]={GETMSB(NDEFfileId ), GETLSB(NDEFfileId )};
	NFC_StatusTypeDef	status ;
	uint16_t	uP1P2 =0x000C, NbByte;
	
	/* build the command */
	command.Header.CLA = C_APDU_CLA_DEFAULT;
	command.Header.INS = C_APDU_SELECT_FILE;
	/* copy the offset */
	command.Header.P1 = GETMSB	(uP1P2 ) ;
	command.Header.P2 = GETLSB	(uP1P2 ) ;
	/* copy the number of byte of the data field */
	command.Body.LC = sizeof(pDataOut) ;
	command.Body.pData = pDataOut;
	/* copy the offset */
	/* build the I²C command */
	M24SR_BuildIBlockCommand (M24SR_CMDSTRUCT_SELECTNDEFFILE,  &command,uDIDbyte, &NbByte , pBuffer);
	
	/* send the request */ 
	errchk( M24SR_IO_SendI2Ccommand (NbByte , pBuffer ));
	errchk( M24SR_IO_IsAnswerReady ());
	/* read the response */ 
	errchk( M24SR_IO_ReceiveI2Cresponse (sizeof(pDataIn) , pDataIn ));

	return M24SR_IsCorrectCRC16Residue (pDataIn,sizeof(pDataIn));
	
Error :
	return NFC_IO_ERROR_I2CTIMEOUT;
	
}

/**
  * @brief  This function sends a read binary command
	* @param	Offset : first byte to read
	* @param	NbByteToRead : number of byte to read
	* @param	pBufferRead : pointer of the buffer read from the M24SR device
  * @retval Status (SW1&SW2) : Status of the operation to complete.
	* @retval M24SR_ERROR_I2CTIMEOUT : The I2C timeout occured.
  */
NFC_StatusTypeDef M24SR::M24SR_ReadBinary (uint16_t Offset ,uint8_t NbByteToRead , uint8_t *pBufferRead )
{
	uint8_t 	*pBuffer = uM24SRbuffer ;
	NFC_StatusTypeDef	status ;
	uint16_t	NbByte;
	
	/* build the command */
	command.Header.CLA = C_APDU_CLA_DEFAULT;
	command.Header.INS = C_APDU_READ_BINARY;
	/* copy the offset */
	command.Header.P1 = GETMSB	(Offset ) ;
	command.Header.P2 = GETLSB	(Offset ) ;
	/* copy the number of byte to read */
	command.Body.LE = NbByteToRead ;
  
	M24SR_BuildIBlockCommand (M24SR_CMDSTRUCT_READBINARY,  &command,uDIDbyte, &NbByte , pBuffer);
  
	errchk( M24SR_IO_SendI2Ccommand (NbByte , pBuffer ));
	errchk( M24SR_IO_IsAnswerReady ());
	errchk( M24SR_IO_ReceiveI2Cresponse (NbByteToRead + M24SR_STATUSRESPONSE_NBBYTE , pBuffer ));
	
	status = M24SR_IsCorrectCRC16Residue (pBuffer,NbByteToRead+ M24SR_STATUSRESPONSE_NBBYTE);
	/* retrieve the data without SW1 & SW2 as provided as return value of the function */
	memcpy(pBufferRead ,&pBuffer[1],NbByteToRead);
	return status;
	
Error :
	return NFC_IO_ERROR_I2CTIMEOUT;
	
}



/**
  * @brief  This function sends a ST read binary command (no error if access is not inside NDEF file)
	* @param	Offset : first byte to read
	* @param	NbByteToRead : number of byte to read
	* @param	pBufferRead : pointer of the buffer read from the M24SR device
  * @retval Status (SW1&SW2) : Status of the operation to complete.
	* @retval M24SR_ERROR_I2CTIMEOUT : The I2C timeout occured. 
  */
NFC_StatusTypeDef M24SR::M24SR_STReadBinary (uint16_t Offset, uint8_t NbByteToRead, uint8_t *pBufferRead )
{
	uint8_t 	*pBuffer = uM24SRbuffer ;
  NFC_StatusTypeDef	status ;
  uint16_t	NbByte;
	
	/* build the command */
	command.Header.CLA = C_APDU_CLA_ST;
	command.Header.INS = C_APDU_READ_BINARY;
	/* copy the offset */
	command.Header.P1 = GETMSB	(Offset ) ;
	command.Header.P2 = GETLSB	(Offset ) ;
	/* copy the number of byte to read */
	command.Body.LE = NbByteToRead ;
  
	M24SR_BuildIBlockCommand (M24SR_CMDSTRUCT_READBINARY,  &command,uDIDbyte, &NbByte , pBuffer);
  
	errchk( M24SR_IO_SendI2Ccommand (NbByte , pBuffer ));
	errchk( M24SR_IO_IsAnswerReady ());
	errchk( M24SR_IO_ReceiveI2Cresponse (NbByteToRead + M24SR_STATUSRESPONSE_NBBYTE , pBuffer ));
	
	status = M24SR_IsCorrectCRC16Residue (pBuffer,NbByteToRead+ M24SR_STATUSRESPONSE_NBBYTE);
	/* retrieve the data without SW1 & SW2 as provided as return value of the function */
	memcpy(pBufferRead ,&pBuffer[1],NbByteToRead);
	return status;
	
Error :
	return NFC_IO_ERROR_I2CTIMEOUT;
	
}

/**
  * @brief  This function sends a Update binary command
	* @param	Offset : first byte to read
	* @param	NbByteToWrite : number of byte to write
	* @param	pBufferRead : pointer of the buffer read from the M24SR device
  * @retval Status (SW1&SW2) : Status of the operation to complete.
	* @retval M24SR_ERROR_I2CTIMEOUT : The I2C timeout occured.
  */
NFC_StatusTypeDef M24SR::M24SR_UpdateBinary (uint16_t Offset ,uint8_t NbByteToWrite,uint8_t *pDataToWrite )
{
	//TODO check the length of the data to write
  uint8_t 	*pBuffer = uM24SRbuffer ;
  NFC_StatusTypeDef	status ;
  uint16_t	NbByte;
	
	/* build the command */
	command.Header.CLA = C_APDU_CLA_DEFAULT;
	command.Header.INS = C_APDU_UPDATE_BINARY;
	/* copy the offset */
	command.Header.P1 = GETMSB	(Offset ) ;
	command.Header.P2 = GETLSB	(Offset ) ;
	/* copy the number of byte of the data field */
	command.Body.LC = NbByteToWrite ;
	/* copy the File Id */
	memcpy(command.Body.pData ,pDataToWrite, NbByteToWrite );
  
	M24SR_BuildIBlockCommand (M24SR_CMDSTRUCT_UPDATEBINARY,  &command,uDIDbyte, &NbByte , pBuffer);
  
	errchk( M24SR_IO_SendI2Ccommand (NbByte , pBuffer ));
	errchk( M24SR_IO_IsAnswerReady ());
	errchk( M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , pBuffer ));
	/* if the response is a Watiting frame extenstion request */ 
	if (IsSBlock (pBuffer) == NFC_IO_SUCCESS)
	{
		/*check the CRC */ 
		if (M24SR_IsCorrectCRC16Residue (pBuffer , M24SR_WATINGTIMEEXTRESPONSE_NBBYTE) != NFC_IO_ERROR_CRC)
		{
			/* send the FrameExension response*/ 
			status = M24SR_FWTExtension (pBuffer [M24SR_OFFSET_PCB+1] );
		}
	}
	else
	{	
		status = M24SR_IsCorrectCRC16Residue (pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
	}
	
	return status;
  
	
Error :
	return NFC_IO_ERROR_I2CTIMEOUT;
}


/**
  * @brief  This function sends the Verify command
	* @param	uPwdId : PasswordId ( 0x0001 : Read NDEF pwd or 0x0002 : Write NDEF pwd or 0x0003 : I2C pwd)
	* @param	NbPwdByte : Number of byte ( 0x00 or 0x10)
	* @param	pPwd : pointer on the passwaord
  * @retval Status (SW1&SW2) : Status of the operation to complete.
	* @retval M24SR_ERROR_I2CTIMEOUT : The I2C timeout occured.
  */
NFC_StatusTypeDef M24SR::M24SR_Verify (uint16_t uPwdId,uint8_t NbPwdByte ,uint8_t *pPwd )
{
	uint8_t 	*pBuffer = uM24SRbuffer ;
  NFC_StatusTypeDef	status = NFC_IO_SUCCESS ;
  uint16_t	NbByte;
  
	/*check the parameters */
	if (uPwdId > 0x0003)
	{	
		return NFC_IO_ERROR_PARAMETER;
	}
	if ( (NbPwdByte != 0x00) && (NbPwdByte != 0x10))
	{	
		return NFC_IO_ERROR_PARAMETER;
	}
  
	/* build the command */
	command.Header.CLA = C_APDU_CLA_DEFAULT;
	command.Header.INS = C_APDU_VERIFY;
	/* copy the Password Id */
	command.Header.P1 = GETMSB	(uPwdId ) ;
	command.Header.P2 = GETLSB	(uPwdId ) ;
	/* copy the number of byte of the data field */
	command.Body.LC = NbPwdByte ;
  
	if (NbPwdByte == 0x10) 
	{
		/* copy the password */
		memcpy(command.Body.pData, pPwd, NbPwdByte);
		/* build the I²C command */
		M24SR_BuildIBlockCommand (M24SR_CMDSTRUCT_VERIFYBINARYWITHPWD,  &command,uDIDbyte, &NbByte , pBuffer);
	}
	else 
	{
		/* build the I²C command */
		M24SR_BuildIBlockCommand (M24SR_CMDSTRUCT_VERIFYBINARYWOPWD,  &command,uDIDbyte, &NbByte , pBuffer);
	}
	
	/* send the request */ 
	errchk( M24SR_IO_SendI2Ccommand (NbByte , pBuffer ));
	/* wait for answer ready */
	errchk( M24SR_IO_IsAnswerReady ());
	/* read the response */ 
	errchk( M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , pBuffer ));
	
	status = M24SR_IsCorrectCRC16Residue (pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
	return status;
	
Error :
	return NFC_IO_ERROR_I2CTIMEOUT;
}


/**
  * @brief  This function sends the ChangeReferenceData command
	* @param	uPwdId : PasswordId ( 0x0001 : Read NDEF pwd or 0x0002 : Write NDEF pwd or 0x0003 : I2C pwd)
	* @param	pPwd : pointer on the passwaord
  * @retval Status (SW1&SW2) : Status of the operation to complete.
	* @retval M24SR_ERROR_I2CTIMEOUT : The I2C timeout occured.
  */
NFC_StatusTypeDef M24SR::M24SR_ChangeReferenceData (uint16_t uPwdId,uint8_t *pPwd )
{
	uint8_t 	*pBuffer = uM24SRbuffer;
  NFC_StatusTypeDef	status ;
  uint16_t	NbByte;
  
	/*check the parameters */
	if (uPwdId > 0x0003)
	{	
		return NFC_IO_ERROR_PARAMETER;
	}
  
	/* build the command */
	command.Header.CLA = C_APDU_CLA_DEFAULT;
	command.Header.INS = C_APDU_CHANGE;
	/* copy the Password Id */
	command.Header.P1 = GETMSB	(uPwdId ) ;
	command.Header.P2 = GETLSB	(uPwdId ) ;
	/* copy the number of byte of the data field */
	command.Body.LC = M24SR_PASSWORD_NBBYTE ;
	/* copy the password */
	memcpy(command.Body.pData, pPwd, M24SR_PASSWORD_NBBYTE);
	/* build the I²C command */
	M24SR_BuildIBlockCommand (M24SR_CMDSTRUCT_CHANGEREFDATA,  &command,uDIDbyte, &NbByte , pBuffer);
  
	
	/* send the request */ 
	errchk( M24SR_IO_SendI2Ccommand (NbByte , pBuffer ));
	errchk( M24SR_IO_IsAnswerReady ());
	/* read the response */ 
	errchk( M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , pBuffer ));
	
	status = M24SR_IsCorrectCRC16Residue (pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
	return status;
  
Error :
	return NFC_IO_ERROR_I2CTIMEOUT;
}


/**
  * @brief  This function sends the EnableVerificationRequirement command
	* @param	uReadOrWrite : enable the read or write protection ( 0x0001 : Read or 0x0002 : Write  )
  * @retval Status (SW1&SW2) : Status of the operation to complete.
	* @retval M24SR_ERROR_I2CTIMEOUT : The I2C timeout occured.
  */
NFC_StatusTypeDef M24SR::M24SR_EnableVerificationRequirement (uint16_t uReadOrWrite  )
{
	uint8_t 	*pBuffer = uM24SRbuffer;
  NFC_StatusTypeDef	status= NFC_IO_SUCCESS ;
  uint16_t	NbByte;
  
	/*check the parameters */
	if ( (uReadOrWrite != 0x0001) && (uReadOrWrite != 0x0002))
	{	
		return NFC_IO_ERROR_PARAMETER;
	}
  
	/* build the command */
	command.Header.CLA = C_APDU_CLA_DEFAULT;
	command.Header.INS = C_APDU_ENABLE;
	/* copy the Password Id */
	command.Header.P1 = GETMSB	(uReadOrWrite ) ;
	command.Header.P2 = GETLSB	(uReadOrWrite ) ;
	/* build the I²C command */
	M24SR_BuildIBlockCommand ( M24SR_CMDSTRUCT_ENABLEVERIFREQ,  &command,uDIDbyte, &NbByte , pBuffer);
  
	/* send the request */ 
	errchk( M24SR_IO_SendI2Ccommand (NbByte , pBuffer ));
	/* The right access to be updated in EEPROM need at least 6ms */	
	errchk( M24SR_IO_IsAnswerReady ());
	/* read the response */ 
	errchk( M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , pBuffer ));
  
	status = M24SR_IsCorrectCRC16Residue ( pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
	return status;
	
Error :
	return NFC_IO_ERROR_I2CTIMEOUT;
}

/**
  * @brief  This function sends the DisableVerificationRequirement command
	* @param	uReadOrWrite : enable the read or write protection ( 0x0001 : Read or 0x0002 : Write  )
  * @retval Status (SW1&SW2) : Status of the operation to complete.
	* @retval M24SR_ERROR_I2CTIMEOUT : The I2C timeout occured.
  */
NFC_StatusTypeDef M24SR::M24SR_DisableVerificationRequirement (uint16_t uReadOrWrite  )
{
	uint8_t 	*pBuffer = uM24SRbuffer;
	NFC_StatusTypeDef	status= NFC_IO_SUCCESS ;
	  uint16_t	NbByte;
  
	/*check the parameters */
	if ( (uReadOrWrite != 0x0001) && (uReadOrWrite != 0x0002))
	{	
		return NFC_IO_ERROR_PARAMETER;
	}
  
	/* build the command */
	command.Header.CLA = C_APDU_CLA_DEFAULT;
	command.Header.INS = C_APDU_DISABLE;
	/* copy the Password Id */
	command.Header.P1 = GETMSB	(uReadOrWrite ) ;
	command.Header.P2 = GETLSB	(uReadOrWrite ) ;
	/* build the I²C command */
	M24SR_BuildIBlockCommand (M24SR_CMDSTRUCT_DISABLEVERIFREQ,  &command,uDIDbyte, &NbByte , pBuffer);
  
	/* send the request */ 
	errchk( M24SR_IO_SendI2Ccommand (NbByte , pBuffer ));
	/* The right access to be updated in EEPROM need at least 6ms */		
	errchk( M24SR_IO_IsAnswerReady ());
	/* read the response */ 
	errchk( M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , pBuffer ));
  
	status = M24SR_IsCorrectCRC16Residue (pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
	return status;
	
Error :
	return NFC_IO_ERROR_I2CTIMEOUT;
}

/**
  * @brief  This function sends the EnablePermananentState command
	* @param	uReadOrWrite : enable the read or write protection ( 0x0001 : Read or 0x0002 : Write  )
  * @retval Status (SW1&SW2) : Status of the operation to complete.
	* @retval M24SR_ERROR_I2CTIMEOUT : The I2C timeout occured.
  */
NFC_StatusTypeDef M24SR::M24SR_EnablePermanentState (uint16_t uReadOrWrite  )
{
	uint8_t 	*pBuffer = uM24SRbuffer;
	NFC_StatusTypeDef	status= NFC_IO_SUCCESS ;
	  uint16_t	NbByte;

	/*check the parameters */
	if ( (uReadOrWrite != 0x0001) && (uReadOrWrite != 0x0002))
	{	
		return NFC_IO_ERROR_PARAMETER;
	}
  
	/* build the command */
	command.Header.CLA = C_APDU_CLA_ST;
	command.Header.INS = C_APDU_ENABLE;
	/* copy the Password Id */
	command.Header.P1 = GETMSB	(uReadOrWrite ) ;
	command.Header.P2 = GETLSB	(uReadOrWrite ) ;
	/* build the I²C command */
	M24SR_BuildIBlockCommand (M24SR_CMDSTRUCT_ENABLEVERIFREQ,  &command,uDIDbyte, &NbByte , pBuffer);
  
	/* send the request */ 
	errchk( M24SR_IO_SendI2Ccommand (NbByte , pBuffer ));
	errchk( M24SR_IO_IsAnswerReady ());
	/* read the response */ 
	errchk( M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , pBuffer ));
  
	status = M24SR_IsCorrectCRC16Residue (pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
	return status;
	
Error :
	return NFC_IO_ERROR_I2CTIMEOUT;
}

/**
  * @brief  This function sends the DisablePermanentState command
	* @param	uReadOrWrite : enable the read or write protection ( 0x0001 : Read or 0x0002 : Write  )
  * @retval Status (SW1&SW2) : Status of the operation to complete.
	* @retval M24SR_ERROR_I2CTIMEOUT : The I2C timeout occured.
  */
NFC_StatusTypeDef M24SR::M24SR_DisablePermanentState (uint16_t uReadOrWrite  )
{
	uint8_t 	*pBuffer = uM24SRbuffer;
	NFC_StatusTypeDef	status= NFC_IO_SUCCESS ;
	  uint16_t	NbByte;
  
	/*check the parameters */
	if ( (uReadOrWrite != 0x0001) && (uReadOrWrite != 0x0002))
	{	
		return NFC_IO_ERROR_PARAMETER;
	}
  
	/* build the command */
	command.Header.CLA = C_APDU_CLA_ST;
	command.Header.INS = C_APDU_DISABLE;
	/* copy the Password Id */
	command.Header.P1 = GETMSB	(uReadOrWrite ) ;
	command.Header.P2 = GETLSB	(uReadOrWrite ) ;
	/* build the I²C command */
	M24SR_BuildIBlockCommand (M24SR_CMDSTRUCT_DISABLEVERIFREQ,  &command,uDIDbyte, &NbByte , pBuffer);
  
	/* send the request */ 
	errchk( M24SR_IO_SendI2Ccommand (NbByte , pBuffer ));
	errchk( M24SR_IO_IsAnswerReady ());
	/* read the response */ 
	errchk( M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , pBuffer ));
  
	status = M24SR_IsCorrectCRC16Residue (pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
	return status;
	
Error :
	return NFC_IO_ERROR_I2CTIMEOUT;
}

/**
  * @brief  This function generates a interrupt on GPO pin
	* @param	None
  * @retval Status (SW1&SW2) : Status of the operation to complete.
	* @retval M24SR_ERROR_I2CTIMEOUT : The I2C timeout occured.
  */
NFC_StatusTypeDef M24SR::M24SR_SendInterrupt ( void  )
{
	uint8_t 	*pBuffer = uM24SRbuffer;
	uint16_t	uP1P2 =0x001E;
	NFC_StatusTypeDef	status= NFC_IO_SUCCESS ;
	  uint16_t	NbByte;
	
	status = M24SR_ManageI2CGPO(INTERRUPT);
	
	/* build the command */
	command.Header.CLA = C_APDU_CLA_ST;
	command.Header.INS = C_APDU_INTERRUPT;
	/* copy the Password Id */
	command.Header.P1 = GETMSB	(uP1P2 ) ;
	command.Header.P2 = GETLSB	(uP1P2 ) ;
	command.Body.LC = 0x00 ;
	/* build the I²C command */
	M24SR_BuildIBlockCommand (M24SR_CMDSTRUCT_SENDINTERRUPT,  &command,uDIDbyte, &NbByte , pBuffer);
  
	/* send the request */ 
	errchk( M24SR_IO_SendI2Ccommand (NbByte , pBuffer ));
	errchk( M24SR_IO_IsAnswerReady ());
	/* read the response */ 
	errchk( M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , pBuffer ));
  
	status = M24SR_IsCorrectCRC16Residue (pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
	return status;
	
Error :
	return NFC_IO_ERROR_I2CTIMEOUT;
}

/**
  * @brief  This function force GPO pin to low state or high Z
	* @param	uSetOrReset : select if GPO must be low (reset) or HiZ
  * @retval Status (SW1&SW2) : Status of the operation to complete.
	* @retval M24SR_ERROR_I2CTIMEOUT : The I2C timeout occured.
  */
NFC_StatusTypeDef M24SR::M24SR_StateControl (uint8_t uSetOrReset )
{
	uint8_t 	*pBuffer = uM24SRbuffer;
	uint16_t	uP1P2 =0x001F;
	NFC_StatusTypeDef	status= NFC_IO_SUCCESS ;
	  uint16_t	NbByte;
	
	/*check the parameters */
	if ( (uSetOrReset != 0x01) && (uSetOrReset != 0x00))
	{	
		return NFC_IO_ERROR_PARAMETER;
	}
	
	status = M24SR_ManageI2CGPO(STATE_CONTROL);
	
	/* build the command */
	command.Header.CLA = C_APDU_CLA_ST;
	command.Header.INS = C_APDU_INTERRUPT;
	/* copy the Password Id */
	command.Header.P1 = GETMSB	(uP1P2 ) ;
	command.Header.P2 = GETLSB	(uP1P2 ) ;
	command.Body.LC = 0x01 ;
	/* copy the data */
	memcpy(command.Body.pData , &uSetOrReset, 0x01 );
	//command.Body.LE = 0x00 ;
	/* build the I²C command */
	M24SR_BuildIBlockCommand ( M24SR_CMDSTRUCT_GPOSTATE,  &command,uDIDbyte, &NbByte , pBuffer);
  
	/* send the request */ 
	errchk( M24SR_IO_SendI2Ccommand (NbByte , pBuffer ));
	errchk( M24SR_IO_IsAnswerReady ());
	/* read the response */ 
	errchk( M24SR_IO_ReceiveI2Cresponse (M24SR_STATUSRESPONSE_NBBYTE , pBuffer ));
  
	status = M24SR_IsCorrectCRC16Residue (pBuffer, M24SR_STATUSRESPONSE_NBBYTE);
	return status;
	
Error :
	return NFC_IO_ERROR_I2CTIMEOUT;
}



/**
  * @brief  This function configure GPO purpose for I2C session
	* @param	GPO_I2Cconfig: GPO configuration to set
  * @retval Status (SW1&SW2) : Status of the operation to complete.
  */
NFC_StatusTypeDef M24SR::M24SR_ManageI2CGPO( uint8_t GPO_I2Cconfig)
{
	NFC_StatusTypeDef status;
	uint8_t GPO_config;
	uint8_t DefaultPassword[16]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};

	if( GPO_I2Cconfig > STATE_CONTROL)
	{
		return NFC_IO_ERROR_PARAMETER;
	}

	/* we must not be in interrupt mode for I2C synchro as we will change GPO purpose */
	M24SR_IO_SetI2CSynchroMode(M24SR_WAITINGTIME_POLLING);

	M24SR_SelectApplication();
	M24SR_SelectSystemfile();
	M24SR_ReadBinary (0x0004 , 0x01 , &GPO_config );

    /* Update only GPO purpose for I2C */
	GPO_config = (GPO_config & 0xF0) | GPO_I2Cconfig;
	M24SR_SelectSystemfile();
	M24SR_Verify(I2C_PWD ,0x10 ,DefaultPassword );
	status = M24SR_UpdateBinary (0x0004 ,0x01, &(GPO_config) );

	M24SR_Deselect();

	/* if we have set interrupt mode for I2C synchro we can enable interrupt mode */
	if ( GPO_I2Cconfig == I2C_ANSWER_READY && status == NFC_OK)
		M24SR_IO_SetI2CSynchroMode(M24SR_INTERRUPT_GPO);

	return status;
}

/**
  * @brief  This function configure GPO purpose for RF session
	* @param	GPO_RFconfig: GPO configuration to set
  * @retval Status (SW1&SW2) : Status of the operation to complete.
  */
NFC_StatusTypeDef M24SR::M24SR_ManageRFGPO(uint8_t GPO_RFconfig)
{
	NFC_StatusTypeDef status;
	uint8_t GPO_config;
	uint8_t DefaultPassword[16]={0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
	
	if( GPO_RFconfig > STATE_CONTROL)
	{	
		return NFC_IO_ERROR_PARAMETER;
	}
	
	M24SR_SelectApplication();
	M24SR_SelectSystemfile();
	M24SR_ReadBinary (0x0004 , 0x01 , &GPO_config );
  
  /* Update only GPO purpose for I2C */	
	GPO_config = (GPO_config & 0x0F) | (GPO_RFconfig<<4);
	M24SR_SelectSystemfile();
	M24SR_Verify(I2C_PWD ,0x10 ,DefaultPassword );
	status = M24SR_UpdateBinary (0x0004 ,0x01, &(GPO_config) );
	
	return status;
}


/**
  * @brief  This function enable or disable RF communication
	* @param	OnOffChoice: GPO configuration to set
  * @retval Status (SW1&SW2) : Status of the operation to complete.
  */
NFC_StatusTypeDef M24SR::M24SR_RFConfig(uint8_t OnOffChoice)
{
	/* Disable RF */
		if ( OnOffChoice != 0 )
		{
			M24SR_IO_RFDIS_WritePin(GPIO_PIN_RESET);
		}
		else
		{
			M24SR_IO_RFDIS_WritePin(GPIO_PIN_SET);
		}
	return NFC_OK;
}



NFC_StatusTypeDef M24SR::M24SR_IO_SendI2Ccommand(uint8_t NbByte , uint8_t *pBuffer){
	int ret = dev_i2c.write(address,(char*)pBuffer,NbByte);
	if(ret==0)
		return NFC_IO_SUCCESS;
	return NFC_IO_ERROR_I2CTIMEOUT;
}

NFC_StatusTypeDef M24SR::M24SR_IO_ReceiveI2Cresponse(uint8_t NbByte , uint8_t *pBuffer){
	int ret = dev_i2c.read(address,(char*)pBuffer,NbByte);
	if(ret==0)
		return NFC_IO_SUCCESS;
	return NFC_IO_ERROR_I2CTIMEOUT;
}


#define M24SR_POLL_DELAY 10
#define M24SR_I2C_POLLING       1 /* In case M24SR will reply ACK failed allow to perform retry before returning error (HAL option not used) */


NFC_StatusTypeDef M24SR::M24SR_IO_PollI2C(void)
{
	int status = 1;
	uint32_t nbTry = 0;
	char buffer;
	//
	wait_ms(M24SR_POLL_DELAY);
	while (status != 0 && nbTry < M24SR_I2C_POLLING)
	{
		status = dev_i2c.read(address, &buffer, 1, false);
		nbTry++;
	}
	if (status == 0)
		return NFC_IO_SUCCESS;
	//else
	return NFC_IO_ERROR_I2CTIMEOUT;
}

NFC_StatusTypeDef M24SR::M24SR_IO_IsAnswerReady(void){
	uint32_t retry = 0xFFFFF;
	int8_t stable = 0;
	GPIO_PinState PinState;

	 switch (syncMode){
	 	 case M24SR_WAITINGTIME_POLLING :
	 		 return M24SR_IO_PollI2C ();

	 	 case M24SR_WAITINGTIME_TIMEOUT :
			// M24SR FWI=5 => (256*16/fc)*2^5=9.6ms but M24SR ask for extended time to program up to 246Bytes.
			// can be improved by
	 		 wait_ms(80);
	 		 return NFC_IO_SUCCESS;

	 	 case M24SR_WAITINGTIME_GPO :
	 		 do{
				M24SR_IO_GPO_ReadPin(&PinState);
				if( PinState == GPIO_PIN_RESET){
					stable ++;
				}
				retry --;
	 		 }
	 		 while(stable <5 && retry>0);
	 		 if(!retry)
	 			 goto Error;
	 		 return NFC_IO_SUCCESS;

	 	 case M24SR_INTERRUPT_GPO :

	 		/* Check if the GPIO is not already low before calling this function */
			M24SR_IO_GPO_ReadPin(&PinState);
			answerReadyInterrupt.enable_irq();
			if(PinState == GPIO_PIN_SET){
				while (!interruptIsFired)
					__WFE();
			}
			interruptIsFired=false;
			answerReadyInterrupt.disable_irq();
			return NFC_IO_SUCCESS;

	  default :
	    return NFC_IO_ERROR_DEFAULT;
	  }

	Error :
	  return NFC_IO_ERROR_DEFAULT;
}


/******************* (C) COPYRIGHT 2013 STMicroelectronics *****END OF FILE****/