pn53x: add timed versions of transceive_bytes/bits

This commit is contained in:
Philippe Teuwen 2011-04-04 14:16:36 +00:00
parent b21d3c6728
commit fb398c387f
9 changed files with 299 additions and 9 deletions

View file

@ -1138,6 +1138,81 @@ pn53x_initiator_transceive_bits (nfc_device_t * pnd, const byte_t * pbtTx, const
return true;
}
bool
pn53x_initiator_transceive_bits_timed (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxBits,
const byte_t * pbtTxPar, byte_t * pbtRx, size_t * pszRxBits, byte_t * pbtRxPar, uint16_t * cycles)
{
unsigned int i;
uint8_t sz, parity;
uint16_t prescaler = 0;
uint16_t reloadval = 0xFFFF;
uint8_t counter_hi, counter_lo;
uint16_t counter;
// We can not just send bytes without parity while the PN53X expects we handled them
if (!pnd->bPar)
return false;
// Sorry, no easy framing support
// TODO: to be changed once we'll provide easy framing support from libnfc itself...
if (pnd->bEasyFraming)
return false;
// Sorry, no CRC support
// TODO: to be changed once we'll provide easy CRC support from libnfc itself...
if (pnd->bCrc)
return false;
// Initialize timer
pn53x_write_register (pnd, REG_CIU_TMODE, 0xFF, SYMBOL_TAUTO | ((prescaler >> 8) & SYMBOL_TPRESCALERHI));
pn53x_write_register (pnd, REG_CIU_TPRESCALER, 0xFF, (prescaler & SYMBOL_TPRESCALERLO));
pn53x_write_register (pnd, REG_CIU_TRELOADVALHI, 0xFF, (reloadval >> 8) & 0xFF);
pn53x_write_register (pnd, REG_CIU_TRELOADVALLO, 0xFF, reloadval & 0xFF);
// Once timer is started, we cannot use Tama commands anymore.
// E.g. on SCL3711 timer settings are reset by 0x42 InCommunicateThru command to:
// 631a=82 631b=a5 631c=02 631d=00
// Prepare FIFO
pn53x_write_register (pnd, REG_CIU_COMMAND, 0xFF, SYMBOL_COMMAND & SYMBOL_COMMAND_TRANSCEIVE);
pn53x_write_register (pnd, REG_CIU_FIFOLEVEL, 0xFF, SYMBOL_FLUSH_BUFFER);
for (i=0; i< ((szTxBits / 8) + 1); i++) {
pn53x_write_register (pnd, REG_CIU_FIFODATA, 0xFF, pbtTx[i]);
}
// Send data
pn53x_write_register (pnd, REG_CIU_BIT_FRAMING, 0xFF, SYMBOL_START_SEND | ((szTxBits % 8) & SYMBOL_TX_LAST_BITS));
// Recv data
pn53x_read_register (pnd, REG_CIU_FIFOLEVEL, &sz);
*pszRxBits = (sz & SYMBOL_FIFO_LEVEL) * 8;
for (i=0; i< sz; i++) {
pn53x_read_register (pnd, REG_CIU_FIFODATA, &(pbtRx[i]));
}
// Read timer
pn53x_read_register (pnd, REG_CIU_TCOUNTERVALHI, &counter_hi);
pn53x_read_register (pnd, REG_CIU_TCOUNTERVALLO, &counter_lo);
counter = counter_hi;
counter = (counter << 8) + counter_lo;
if (counter == 0) {
// counter saturated
*cycles = 0xFFFF;
} else {
*cycles = 0xFFFF - counter + 1;
// Correction, depending on last parity bit sent
sz = pbtTx[szTxBits / 8];
parity = (sz >> 7) ^ ((sz >> 6) & 1) ^ ((sz >> 5) & 1) ^ ((sz >> 4) & 1) ^ ((sz >> 3) & 1) ^ ((sz >> 2) & 1) ^ ((sz >> 1) & 1) ^ (sz & 1);
parity = parity ? 0:1;
if (parity) {
*cycles += CHIP_DATA(pnd)->timer_correction_yy;
} else {
*cycles += CHIP_DATA(pnd)->timer_correction_zy;
}
}
return true;
}
bool
pn53x_initiator_transceive_bytes (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx,
size_t * pszRx)
@ -1182,6 +1257,80 @@ pn53x_initiator_transceive_bytes (nfc_device_t * pnd, const byte_t * pbtTx, cons
return true;
}
bool
pn53x_initiator_transceive_bytes_timed (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx, byte_t * pbtRx,
size_t * pszRx, uint16_t * cycles)
{
unsigned int i;
uint8_t sz, parity;
uint16_t prescaler = 0;
uint16_t reloadval = 0xFFFF;
uint8_t counter_hi, counter_lo;
uint16_t counter;
// We can not just send bytes without parity while the PN53X expects we handled them
if (!pnd->bPar)
return false;
// Sorry, no easy framing support
// TODO: to be changed once we'll provide easy framing support from libnfc itself...
if (pnd->bEasyFraming)
return false;
// Sorry, no CRC support
// TODO: to be changed once we'll provide easy CRC support from libnfc itself...
if (pnd->bCrc)
return false;
// Initialize timer
pn53x_write_register (pnd, REG_CIU_TMODE, 0xFF, SYMBOL_TAUTO | ((prescaler >> 8) & SYMBOL_TPRESCALERHI));
pn53x_write_register (pnd, REG_CIU_TPRESCALER, 0xFF, (prescaler & SYMBOL_TPRESCALERLO));
pn53x_write_register (pnd, REG_CIU_TRELOADVALHI, 0xFF, (reloadval >> 8) & 0xFF);
pn53x_write_register (pnd, REG_CIU_TRELOADVALLO, 0xFF, reloadval & 0xFF);
// Once timer is started, we cannot use Tama commands anymore.
// E.g. on SCL3711 timer settings are reset by 0x42 InCommunicateThru command to:
// 631a=82 631b=a5 631c=02 631d=00
// Prepare FIFO
pn53x_write_register (pnd, REG_CIU_COMMAND, 0xFF, SYMBOL_COMMAND & SYMBOL_COMMAND_TRANSCEIVE);
pn53x_write_register (pnd, REG_CIU_FIFOLEVEL, 0xFF, SYMBOL_FLUSH_BUFFER);
for (i=0; i< szTx; i++) {
pn53x_write_register (pnd, REG_CIU_FIFODATA, 0xFF, pbtTx[i]);
}
// Send data
pn53x_write_register (pnd, REG_CIU_BIT_FRAMING, 0xFF, SYMBOL_START_SEND);
// Recv data
pn53x_read_register (pnd, REG_CIU_FIFOLEVEL, &sz);
*pszRx = sz & SYMBOL_FIFO_LEVEL;
for (i=0; i< sz; i++) {
pn53x_read_register (pnd, REG_CIU_FIFODATA, &(pbtRx[i]));
}
// Read timer
pn53x_read_register (pnd, REG_CIU_TCOUNTERVALHI, &counter_hi);
pn53x_read_register (pnd, REG_CIU_TCOUNTERVALLO, &counter_lo);
counter = counter_hi;
counter = (counter << 8) + counter_lo;
if (counter == 0) {
// counter saturated
*cycles = 0xFFFF;
} else {
*cycles = 0xFFFF - counter + 1;
// Correction, depending on last parity bit sent
sz = pbtTx[szTx -1];
parity = (sz >> 7) ^ ((sz >> 6) & 1) ^ ((sz >> 5) & 1) ^ ((sz >> 4) & 1) ^ ((sz >> 3) & 1) ^ ((sz >> 2) & 1) ^ ((sz >> 1) & 1) ^ (sz & 1);
parity = parity ? 0:1;
if (parity) {
*cycles += CHIP_DATA(pnd)->timer_correction_yy;
} else {
*cycles += CHIP_DATA(pnd)->timer_correction_zy;
}
}
return true;
}
#define SAK_ISO14443_4_COMPLIANT 0x20
bool
pn53x_target_init (nfc_device_t * pnd, nfc_target_t * pnt, byte_t * pbtRx, size_t * pszRx)

View file

@ -39,6 +39,11 @@
// 11 : ISO/IEC 14443B
# define SYMBOL_TX_FRAMING 0x03
# define REG_CONTROL_SWITCH_RNG 0x6106
# define SYMBOL_CURLIMOFF 0x08 /* When set to 1, the 100 mA current limitations is desactivated. */
# define SYMBOL_SIC_SWITCH_EN 0x10 /* When set to logic 1, the SVDD switch is enabled and the SVDD output delivers power to secure IC and internal pads (SIGIN, SIGOUT and P34). */
# define SYMBOL_RANDOM_DATAREADY 0x02 /* When set to logic 1, a new random number is available. */
# define REG_CIU_RX_MODE 0x6303
# define SYMBOL_RX_CRC_ENABLE 0x80
# define SYMBOL_RX_NO_ERROR 0x08
@ -51,29 +56,50 @@
# define SYMBOL_AUTO_WAKE_UP 0x20
# define SYMBOL_INITIAL_RF_ON 0x04
# define REG_CIU_TXSEL 0x6306
# define REG_CIU_MANUAL_RCV 0x630D
# define SYMBOL_PARITY_DISABLE 0x10
# define REG_CIU_TMODE 0x631A
# define SYMBOL_TAUTO 0x80
# define SYMBOL_TPRESCALERHI 0x0F
# define REG_CIU_TPRESCALER 0x631B
# define SYMBOL_TPRESCALERLO 0xFF
# define REG_CIU_TRELOADVALHI 0x631C
# define REG_CIU_TRELOADVALLO 0x631D
# define REG_CIU_TCOUNTERVALHI 0x631E
# define REG_CIU_TCOUNTERVALLO 0x631F
# define REG_CIU_COMMAND 0x6331
# define SYMBOL_COMMAND 0x0F
# define SYMBOL_COMMAND_TRANSCEIVE 0xC
# define REG_CIU_STATUS2 0x6338
# define SYMBOL_MF_CRYPTO1_ON 0x08
# define REG_CIU_FIFODATA 0x6339
# define REG_CIU_FIFOLEVEL 0x633A
# define SYMBOL_FLUSH_BUFFER 0x80
# define SYMBOL_FIFO_LEVEL 0x7F
# define REG_CIU_CONTROL 0x633C
# define SYMBOL_INITIATOR 0x10
# define SYMBOL_RX_LAST_BITS 0x07
# define REG_CIU_BIT_FRAMING 0x633D
# define SYMBOL_START_SEND 0x80
# define SYMBOL_RX_ALIGN 0x70
# define SYMBOL_TX_LAST_BITS 0x07
# define REG_CONTROL_SWITCH_RNG 0x6106
# define SYMBOL_CURLIMOFF 0x08 /* When set to 1, the 100 mA current limitations is desactivated. */
# define SYMBOL_SIC_SWITCH_EN 0x10 /* When set to logic 1, the SVDD switch is enabled and the SVDD output delivers power to secure IC and internal pads (SIGIN, SIGOUT and P34). */
# define SYMBOL_RANDOM_DATAREADY 0x02 /* When set to logic 1, a new random number is available. */
# define REG_CIU_TXSEL 0x6306
# define SFR_P3CFGB 0xFFFD
# define SFR_P3 0xFFB0
// PN53X Support Byte flags
#define SUPPORT_ISO14443A 0x01
#define SUPPORT_ISO14443B 0x02
@ -131,6 +157,10 @@ struct pn53x_data {
uint8_t ui8Parameters;
/** Last sent command */
uint8_t ui8LastCommand;
/** Interframe correction for commands ending with logic "1" */
int16_t timer_correction_yy;
/** Interframe correction for commands ending with logic "0" */
int16_t timer_correction_zy;
};
#define CHIP_DATA(pnd) ((struct pn53x_data*)(pnd->chip_data))
@ -254,6 +284,11 @@ bool pn53x_initiator_transceive_bits (nfc_device_t * pnd, const byte_t * pbtT
byte_t * pbtRxPar);
bool pn53x_initiator_transceive_bytes (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx,
byte_t * pbtRx, size_t * pszRx);
bool pn53x_initiator_transceive_bits_timed (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxBits,
const byte_t * pbtTxPar, byte_t * pbtRx, size_t * pszRxBits,
byte_t * pbtRxPar, uint16_t * cycles);
bool pn53x_initiator_transceive_bytes_timed (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTx,
byte_t * pbtRx, size_t * pszRx, uint16_t * cycles);
bool pn53x_initiator_deselect_target (nfc_device_t * pnd);
// NFC device as Target functions