2022-04-28 02:04:02 +02:00

656 lines
22 KiB
C

/******************************************************************************
* \attention
*
* <h2><center>&copy; COPYRIGHT 2016 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* PROJECT: ST25R3911 firmware
* Revision:
* LANGUAGE: ISO C99
*/
/*! \file
*
* \author Ulrich Herrmann
*
* \brief ST25R3911 high level interface
*
*/
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include "st25r3911.h"
#include "st25r3911_com.h"
#include "st25r3911_interrupt.h"
#include "utils.h"
/*
******************************************************************************
* LOCAL DEFINES
******************************************************************************
*/
#define ST25R3911_OSC_STABLE_TIMEOUT 10U /*!< Timeout for Oscillator to get stable, datasheet: 700us, take 5 ms */
#define ST25R3911_CA_TIMEOUT 10U /*!< Timeout for Collision Avoidance command */
#define ST25R3911_TOUT_CALIBRATE_CAP_SENSOR 4U /*!< Max duration Calibrate Capacitive Sensor command Datasheet: 3ms */
/*
******************************************************************************
* LOCAL CONSTANTS
******************************************************************************
*/
/*
******************************************************************************
* LOCAL VARIABLES
******************************************************************************
*/
static uint32_t st25r3911NoResponseTime_64fcs;
/*
******************************************************************************
* LOCAL FUNCTION PROTOTYPES
******************************************************************************
*/
static ReturnCode st25r3911ExecuteCommandAndGetResult(uint8_t cmd, uint8_t resreg, uint8_t sleeptime, uint8_t* result);
/*
******************************************************************************
* GLOBAL FUNCTIONS
******************************************************************************
*/
void st25r3911TxRxOn( void )
{
st25r3911SetRegisterBits(ST25R3911_REG_OP_CONTROL, (ST25R3911_REG_OP_CONTROL_rx_en | ST25R3911_REG_OP_CONTROL_tx_en) );
}
void st25r3911TxRxOff( void )
{
st25r3911ClrRegisterBits(ST25R3911_REG_OP_CONTROL, (ST25R3911_REG_OP_CONTROL_rx_en | ST25R3911_REG_OP_CONTROL_tx_en) );
}
void st25r3911OscOn( void )
{
/* Check if oscillator is already turned on and stable */
/* Use ST25R3911_REG_OP_CONTROL_en instead of ST25R3911_REG_AUX_DISPLAY_osc_ok to be on the safe side */
if( !st25r3911CheckReg( ST25R3911_REG_OP_CONTROL, ST25R3911_REG_OP_CONTROL_en, ST25R3911_REG_OP_CONTROL_en ) )
{
/* Clear any eventual previous oscillator IRQ */
st25r3911GetInterrupt( ST25R3911_IRQ_MASK_OSC );
/* enable oscillator frequency stable interrupt */
st25r3911EnableInterrupts(ST25R3911_IRQ_MASK_OSC);
/* enable oscillator and regulator output */
st25r3911ModifyRegister(ST25R3911_REG_OP_CONTROL, 0x00, ST25R3911_REG_OP_CONTROL_en);
/* wait for the oscillator interrupt */
st25r3911WaitForInterruptsTimed(ST25R3911_IRQ_MASK_OSC, ST25R3911_OSC_STABLE_TIMEOUT);
st25r3911DisableInterrupts(ST25R3911_IRQ_MASK_OSC);
}
}
void st25r3911Initialize(void)
{
uint16_t vdd_mV;
/* first, reset the st25r3911 */
st25r3911ExecuteCommand(ST25R3911_CMD_SET_DEFAULT);
/* Set Operation Control Register to default value */
st25r3911WriteRegister(ST25R3911_REG_OP_CONTROL, 0x00);
/* enable pull downs on miso line */
st25r3911ModifyRegister(ST25R3911_REG_IO_CONF2, 0,
ST25R3911_REG_IO_CONF2_miso_pd1 |
ST25R3911_REG_IO_CONF2_miso_pd2);
/* after reset all interrupts are enabled. so disable them at first */
st25r3911DisableInterrupts(ST25R3911_IRQ_MASK_ALL);
/* and clear them, just to be sure... */
st25r3911ClearInterrupts();
st25r3911OscOn();
/* Measure vdd and set sup3V bit accordingly */
vdd_mV = st25r3911MeasureVoltage(ST25R3911_REG_REGULATOR_CONTROL_mpsv_vdd);
st25r3911ModifyRegister(ST25R3911_REG_IO_CONF2,
ST25R3911_REG_IO_CONF2_sup3V,
(uint8_t)((vdd_mV < 3600U)?ST25R3911_REG_IO_CONF2_sup3V:0U));
/* Make sure Transmitter and Receiver are disabled */
st25r3911TxRxOff();
return;
}
void st25r3911Deinitialize(void)
{
st25r3911DisableInterrupts(ST25R3911_IRQ_MASK_ALL);
/* Disabe Tx and Rx, Keep OSC */
st25r3911TxRxOff();
return;
}
ReturnCode st25r3911AdjustRegulators(uint16_t* result_mV)
{
uint8_t result;
uint8_t io_conf2;
ReturnCode err = ERR_NONE;
/* Reset logic and set regulated voltages to be defined by result of Adjust Regulators command */
st25r3911SetRegisterBits( ST25R3911_REG_REGULATOR_CONTROL, ST25R3911_REG_REGULATOR_CONTROL_reg_s );
st25r3911ClrRegisterBits( ST25R3911_REG_REGULATOR_CONTROL, ST25R3911_REG_REGULATOR_CONTROL_reg_s );
st25r3911ExecuteCommandAndGetResult(ST25R3911_CMD_ADJUST_REGULATORS,
ST25R3911_REG_REGULATOR_RESULT,
5,
&result);
st25r3911ReadRegister(ST25R3911_REG_IO_CONF2, &io_conf2);
result >>= ST25R3911_REG_REGULATOR_RESULT_shift_reg;
result -= 5U;
if (result_mV != NULL)
{
if((io_conf2 & ST25R3911_REG_IO_CONF2_sup3V) != 0U)
{
*result_mV = 2400;
*result_mV += (uint16_t)result * 100U;
}
else
{
*result_mV = 3900;
*result_mV += (uint16_t)result * 120U;
}
}
return err;
}
void st25r3911MeasureAmplitude(uint8_t* result)
{
st25r3911ExecuteCommandAndGetResult(ST25R3911_CMD_MEASURE_AMPLITUDE,
ST25R3911_REG_AD_RESULT,
10,
result);
}
void st25r3911MeasurePhase(uint8_t* result)
{
st25r3911ExecuteCommandAndGetResult(ST25R3911_CMD_MEASURE_PHASE,
ST25R3911_REG_AD_RESULT,
10,
result);
}
void st25r3911MeasureCapacitance(uint8_t* result)
{
st25r3911ExecuteCommandAndGetResult(ST25R3911_CMD_MEASURE_CAPACITANCE,
ST25R3911_REG_AD_RESULT,
10,
result);
}
void st25r3911CalibrateAntenna(uint8_t* result)
{
st25r3911ExecuteCommandAndGetResult(ST25R3911_CMD_CALIBRATE_ANTENNA,
ST25R3911_REG_ANT_CAL_RESULT,
10,
result);
}
void st25r3911CalibrateModulationDepth(uint8_t* result)
{
st25r3911ExecuteCommandAndGetResult(ST25R3911_CMD_CALIBRATE_MODULATION,
ST25R3911_REG_AM_MOD_DEPTH_RESULT,
10,
result);
}
ReturnCode st25r3911CalibrateCapacitiveSensor(uint8_t* result)
{
ReturnCode ret;
uint8_t res;
/* Clear Manual calibration values to enable automatic calibration mode */
st25r3911ClrRegisterBits( ST25R3911_REG_CAP_SENSOR_CONTROL, ST25R3916_REG_CAP_SENSOR_CONTROL_mask_cs_mcal );
/* Execute automatic calibration */
ret = st25r3911ExecuteCommandAndGetResult( ST25R3911_CMD_CALIBRATE_C_SENSOR, ST25R3911_REG_CAP_SENSOR_RESULT, ST25R3911_TOUT_CALIBRATE_CAP_SENSOR, &res );
/* Check wether the calibration was successull */
if( ((res & ST25R3911_REG_CAP_SENSOR_RESULT_cs_cal_end) != ST25R3911_REG_CAP_SENSOR_RESULT_cs_cal_end) ||
((res & ST25R3911_REG_CAP_SENSOR_RESULT_cs_cal_err) == ST25R3911_REG_CAP_SENSOR_RESULT_cs_cal_err) || (ret != ERR_NONE) )
{
return ERR_IO;
}
if( result != NULL )
{
(*result) = (uint8_t)(res >> ST25R3911_REG_CAP_SENSOR_CONTROL_shift_cs_mcal);
}
return ERR_NONE;
}
ReturnCode st25r3911SetBitrate(uint8_t txRate, uint8_t rxRate)
{
uint8_t reg;
st25r3911ReadRegister(ST25R3911_REG_BIT_RATE, &reg);
if (rxRate != ST25R3911_BR_DO_NOT_SET)
{
if(rxRate > ST25R3911_BR_3390)
{
return ERR_PARAM;
}
else
{
reg = (uint8_t)(reg & ~ST25R3911_REG_BIT_RATE_mask_rxrate); /* MISRA 10.3 */
reg |= rxRate << ST25R3911_REG_BIT_RATE_shift_rxrate;
}
}
if (txRate != ST25R3911_BR_DO_NOT_SET)
{
if(txRate > ST25R3911_BR_6780)
{
return ERR_PARAM;
}
else
{
reg = (uint8_t)(reg & ~ST25R3911_REG_BIT_RATE_mask_txrate); /* MISRA 10.3 */
reg |= txRate<<ST25R3911_REG_BIT_RATE_shift_txrate;
}
}
st25r3911WriteRegister(ST25R3911_REG_BIT_RATE, reg);
return ERR_NONE;
}
uint8_t st25r3911MeasurePowerSupply( uint8_t mpsv )
{
uint8_t result;
/* Set the source of direct command: Measure Power Supply Voltage */
st25r3911ChangeRegisterBits( ST25R3911_REG_REGULATOR_CONTROL, ST25R3911_REG_REGULATOR_CONTROL_mask_mpsv, mpsv );
/* Execute command: Measure Power Supply Voltage */
st25r3911ExecuteCommandAndGetResult( ST25R3911_CMD_MEASURE_VDD, ST25R3911_REG_AD_RESULT, 10, &result);
return result;
}
uint16_t st25r3911MeasureVoltage(uint8_t mpsv)
{
uint8_t result;
uint16_t mV;
result = st25r3911MeasurePowerSupply( mpsv );
mV = ((uint16_t)result) * 23U;
mV += ((((uint16_t)result) * 438U) + 500U) / 1000U;
return mV;
}
uint8_t st25r3911GetNumFIFOLastBits(void)
{
uint8_t reg;
st25r3911ReadRegister( ST25R3911_REG_FIFO_RX_STATUS2, &reg );
return ((reg & ST25R3911_REG_FIFO_RX_STATUS2_mask_fifo_lb) >> ST25R3911_REG_FIFO_RX_STATUS2_shift_fifo_lb);
}
uint32_t st25r3911GetNoResponseTime_64fcs(void)
{
return st25r3911NoResponseTime_64fcs;
}
void st25r3911StartGPTimer_8fcs(uint16_t gpt_8fcs, uint8_t trigger_source)
{
st25r3911SetGPTime_8fcs(gpt_8fcs);
st25r3911ModifyRegister(ST25R3911_REG_GPT_CONTROL,
ST25R3911_REG_GPT_CONTROL_gptc_mask,
trigger_source);
if (trigger_source == 0U)
{
st25r3911ExecuteCommand(ST25R3911_CMD_START_GP_TIMER);
}
return;
}
void st25r3911SetGPTime_8fcs(uint16_t gpt_8fcs)
{
st25r3911WriteRegister(ST25R3911_REG_GPT1, (uint8_t)(gpt_8fcs >> 8));
st25r3911WriteRegister(ST25R3911_REG_GPT2, (uint8_t)(gpt_8fcs & 0xffU));
return;
}
bool st25r3911CheckReg( uint8_t reg, uint8_t mask, uint8_t value )
{
uint8_t regVal;
regVal = 0;
st25r3911ReadRegister( reg, &regVal );
return ((regVal & mask) == value );
}
bool st25r3911CheckChipID( uint8_t *rev )
{
uint8_t ID;
ID = 0;
st25r3911ReadRegister( ST25R3911_REG_IC_IDENTITY, &ID );
/* Check if IC Identity Register contains ST25R3911's IC type code */
if( (ID & ST25R3911_REG_IC_IDENTITY_mask_ic_type) != ST25R3911_REG_IC_IDENTITY_ic_type )
{
return false;
}
if(rev != NULL)
{
*rev = (ID & ST25R3911_REG_IC_IDENTITY_mask_ic_rev);
}
return true;
}
ReturnCode st25r3911SetNoResponseTime_64fcs(uint32_t nrt_64fcs)
{
ReturnCode err = ERR_NONE;
uint8_t nrt_step = 0;
uint32_t noResponseTime_64fcs = nrt_64fcs; /* MISRA 17.8: Use intermediate variable */
st25r3911NoResponseTime_64fcs = noResponseTime_64fcs;
if (noResponseTime_64fcs > (uint32_t)0xFFFFU)
{
nrt_step = ST25R3911_REG_GPT_CONTROL_nrt_step;
noResponseTime_64fcs = (noResponseTime_64fcs + 63U) / 64U;
if (noResponseTime_64fcs > (uint32_t)0xFFFFU)
{
noResponseTime_64fcs = 0xFFFFU;
err = ERR_PARAM;
}
st25r3911NoResponseTime_64fcs = 64U * noResponseTime_64fcs;
}
st25r3911ModifyRegister(ST25R3911_REG_GPT_CONTROL, ST25R3911_REG_GPT_CONTROL_nrt_step, nrt_step);
st25r3911WriteRegister(ST25R3911_REG_NO_RESPONSE_TIMER1, (uint8_t)(noResponseTime_64fcs >> 8));
st25r3911WriteRegister(ST25R3911_REG_NO_RESPONSE_TIMER2, (uint8_t)(noResponseTime_64fcs & 0xffU));
return err;
}
ReturnCode st25r3911SetStartNoResponseTime_64fcs(uint32_t nrt_64fcs)
{
ReturnCode err;
err = st25r3911SetNoResponseTime_64fcs( nrt_64fcs );
if(err == ERR_NONE)
{
st25r3911ExecuteCommand(ST25R3911_CMD_START_NO_RESPONSE_TIMER);
}
return err;
}
ReturnCode st25r3911PerformCollisionAvoidance( uint8_t FieldONCmd, uint8_t pdThreshold, uint8_t caThreshold, uint8_t nTRFW )
{
uint8_t treMask;
uint32_t irqs;
if( (FieldONCmd != ST25R3911_CMD_INITIAL_RF_COLLISION) &&
(FieldONCmd != ST25R3911_CMD_RESPONSE_RF_COLLISION_0) &&
(FieldONCmd != ST25R3911_CMD_RESPONSE_RF_COLLISION_N) )
{
return ERR_PARAM;
}
/* Check if new thresholds are to be applied */
if( (pdThreshold != ST25R3911_THRESHOLD_DO_NOT_SET) || (caThreshold != ST25R3911_THRESHOLD_DO_NOT_SET) )
{
treMask = 0;
if(pdThreshold != ST25R3911_THRESHOLD_DO_NOT_SET)
{
treMask |= ST25R3911_REG_FIELD_THRESHOLD_mask_trg;
}
if(caThreshold != ST25R3911_THRESHOLD_DO_NOT_SET)
{
treMask |= ST25R3911_REG_FIELD_THRESHOLD_mask_rfe;
}
/* Set Detection Threshold and|or Collision Avoidance Threshold */
st25r3911ChangeRegisterBits( ST25R3911_REG_FIELD_THRESHOLD, treMask, (pdThreshold & ST25R3911_REG_FIELD_THRESHOLD_mask_trg) | (caThreshold & ST25R3911_REG_FIELD_THRESHOLD_mask_rfe ) );
}
/* Set n x TRFW */
st25r3911ModifyRegister(ST25R3911_REG_AUX, ST25R3911_REG_AUX_mask_nfc_n, (nTRFW & ST25R3911_REG_AUX_mask_nfc_n) );
/* Enable and clear CA specific interrupts and execute command */
st25r3911EnableInterrupts( (ST25R3911_IRQ_MASK_CAC | ST25R3911_IRQ_MASK_CAT) );
st25r3911GetInterrupt( (ST25R3911_IRQ_MASK_CAC | ST25R3911_IRQ_MASK_CAT) );
st25r3911ExecuteCommand(FieldONCmd);
irqs = st25r3911WaitForInterruptsTimed(ST25R3911_IRQ_MASK_CAC | ST25R3911_IRQ_MASK_CAT, ST25R3911_CA_TIMEOUT );
/* Clear any previous External Field events and disable CA specific interrupts */
st25r3911GetInterrupt( (ST25R3911_IRQ_MASK_EOF | ST25R3911_IRQ_MASK_EON) );
st25r3911DisableInterrupts(ST25R3911_IRQ_MASK_CAC | ST25R3911_IRQ_MASK_CAT);
if((ST25R3911_IRQ_MASK_CAC & irqs) != 0U) /* Collision occurred */
{
return ERR_RF_COLLISION;
}
if((ST25R3911_IRQ_MASK_CAT & irqs) != 0U) /* No Collision detected, Field On */
{
return ERR_NONE;
}
/* No interrupt detected */
return ERR_INTERNAL;
}
ReturnCode st25r3911GetRegsDump(uint8_t* resRegDump, uint8_t* sizeRegDump)
{
uint8_t regIt;
uint8_t regDump[ST25R3911_REG_IC_IDENTITY+1U];
if(!sizeRegDump || !resRegDump)
{
return ERR_PARAM;
}
for( regIt = ST25R3911_REG_IO_CONF1; regIt < SIZEOF_ARRAY(regDump); regIt++ )
{
st25r3911ReadRegister(regIt, &regDump[regIt] );
}
*sizeRegDump = MIN(*sizeRegDump, regIt);
if( *sizeRegDump > 0U ) /* MISRA 21.18 */
{
ST_MEMCPY(resRegDump, regDump, *sizeRegDump );
}
return ERR_NONE;
}
void st25r3911SetNumTxBits( uint32_t nBits )
{
st25r3911WriteRegister(ST25R3911_REG_NUM_TX_BYTES2, (uint8_t)((nBits >> 0) & 0xffU));
st25r3911WriteRegister(ST25R3911_REG_NUM_TX_BYTES1, (uint8_t)((nBits >> 8) & 0xffU));
}
bool st25r3911IsCmdValid( uint8_t cmd )
{
if( !((cmd >= ST25R3911_CMD_SET_DEFAULT) && (cmd <= ST25R3911_CMD_ANALOG_PRESET)) &&
!((cmd >= ST25R3911_CMD_MASK_RECEIVE_DATA) && (cmd <= ST25R3911_CMD_CLEAR_RSSI)) &&
!((cmd >= ST25R3911_CMD_TRANSPARENT_MODE) && (cmd <= ST25R3911_CMD_START_NO_RESPONSE_TIMER)) &&
!((cmd >= ST25R3911_CMD_TEST_CLEARA) && (cmd <= ST25R3911_CMD_FUSE_PPROM)) )
{
return false;
}
return true;
}
ReturnCode st25r3911StreamConfigure(const struct st25r3911StreamConfig *config)
{
uint8_t smd = 0;
uint8_t mode;
if (config->useBPSK != 0U)
{
mode = ST25R3911_REG_MODE_om_bpsk_stream;
if ((config->din<2U) || (config->din>4U)) /* not in fc/4 .. fc/16 */
{
return ERR_PARAM;
}
smd |= (4U - config->din) << ST25R3911_REG_STREAM_MODE_shift_scf;
}
else
{
mode = ST25R3911_REG_MODE_om_subcarrier_stream;
if ((config->din<3U) || (config->din>6U)) /* not in fc/8 .. fc/64 */
{
return ERR_PARAM;
}
smd |= (6U - config->din) << ST25R3911_REG_STREAM_MODE_shift_scf;
if (config->report_period_length == 0U)
{
return ERR_PARAM;
}
}
if ((config->dout<1U) || (config->dout>7U)) /* not in fc/2 .. fc/128 */
{
return ERR_PARAM;
}
smd |= (7U - config->dout) << ST25R3911_REG_STREAM_MODE_shift_stx;
if (config->report_period_length > 3U)
{
return ERR_PARAM;
}
smd |= config->report_period_length << ST25R3911_REG_STREAM_MODE_shift_scp;
st25r3911WriteRegister(ST25R3911_REG_STREAM_MODE, smd);
st25r3911ChangeRegisterBits(ST25R3911_REG_MODE, ST25R3911_REG_MODE_mask_om, mode);
return ERR_NONE;
}
/*******************************************************************************/
ReturnCode st25r3911GetRSSI( uint16_t *amRssi, uint16_t *pmRssi )
{
/*******************************************************************************/
/* MISRA 8.9 An object should be defined at block scope if its identifier only appears in a single function */
/*< ST25R3911 RSSI Display Reg values:0 1 2 3 4 5 6 7 8 9 a b c d e f */
const uint16_t st25r3911Rssi2mV[] = { 0 ,20 ,27 ,37 ,52 ,72 ,99 ,136 ,190 ,262 ,357 ,500 ,686 ,950, 0, 0 };
/* ST25R3911 2/3 stage gain reduction [dB] 0 0 0 0 0 3 6 9 12 15 18 na na na na na */
const uint16_t st25r3911Gain2Percent[] = { 100, 100, 100, 100, 100, 141, 200, 281, 398, 562, 794, 1, 1, 1, 1, 1 };
/*******************************************************************************/
uint8_t rssi;
uint8_t gainRed;
st25r3911ReadRegister( ST25R3911_REG_RSSI_RESULT, &rssi );
st25r3911ReadRegister( ST25R3911_REG_GAIN_RED_STATE, &gainRed );
if( amRssi != NULL )
{
*amRssi = (uint16_t) ( ( (uint32_t)st25r3911Rssi2mV[ (rssi >> ST25R3911_REG_RSSI_RESULT_shift_rssi_am) ] * (uint32_t)st25r3911Gain2Percent[ (gainRed >> ST25R3911_REG_GAIN_RED_STATE_shift_gs_am) ] ) / 100U );
}
if( pmRssi != NULL )
{
*pmRssi = (uint16_t) ( ( (uint32_t)st25r3911Rssi2mV[ (rssi & ST25R3911_REG_RSSI_RESULT_mask_rssi_pm) ] * (uint32_t)st25r3911Gain2Percent[ (gainRed & ST25R3911_REG_GAIN_RED_STATE_mask_gs_pm) ] ) / 100U );
}
return ERR_NONE;
}
/*
******************************************************************************
* LOCAL FUNCTIONS
******************************************************************************
*/
/*!
*****************************************************************************
* \brief Executes a direct command and returns the result
*
* This function executes the direct command given by \a cmd waits for
* \a sleeptime for I_dct and returns the result read from register \a resreg.
* No checking of the validity of the cmd is performed.
*
* \param[in] cmd: direct command to execute.
* \param[in] resreg: Address of the register containing the result.
* \param[in] sleeptime: time in milliseconds to wait before reading the result.
* \param[out] result: 8 bit long result
*
*****************************************************************************
*/
static ReturnCode st25r3911ExecuteCommandAndGetResult(uint8_t cmd, uint8_t resreg, uint8_t sleeptime, uint8_t* result)
{
st25r3911EnableInterrupts(ST25R3911_IRQ_MASK_DCT);
st25r3911GetInterrupt(ST25R3911_IRQ_MASK_DCT);
st25r3911ExecuteCommand(cmd);
st25r3911WaitForInterruptsTimed(ST25R3911_IRQ_MASK_DCT, sleeptime);
st25r3911DisableInterrupts(ST25R3911_IRQ_MASK_DCT);
/* read out the result if the pointer is not NULL */
if (result != NULL)
{
st25r3911ReadRegister(resreg, result);
}
return ERR_NONE;
}