From ffe2714b286c3c4a60ee96f4f74b8534434c5caa Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 4 Apr 2011 19:04:43 +0000 Subject: [PATCH] pn53x: factorize timer code --- libnfc/chips/pn53x.c | 120 +++++++++++++++++------------------- libnfc/chips/pn53x.h | 6 +- libnfc/drivers/acr122.c | 8 +-- libnfc/drivers/arygon.c | 9 +-- libnfc/drivers/pn532_uart.c | 9 +-- libnfc/drivers/pn53x_usb.c | 18 ++---- 6 files changed, 70 insertions(+), 100 deletions(-) diff --git a/libnfc/chips/pn53x.c b/libnfc/chips/pn53x.c index 7e3dc1f..ce28d2b 100644 --- a/libnfc/chips/pn53x.c +++ b/libnfc/chips/pn53x.c @@ -1075,6 +1075,56 @@ pn53x_InJumpForDEP (nfc_device_t * pnd, return true; } +void __pn53x_init_timer(nfc_device_t * pnd) +{ + uint16_t prescaler = 0; + uint16_t reloadval = 0xFFFF; + // 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); +} + +uint16_t __pn53x_get_timer(nfc_device_t * pnd, const uint8_t last_cmd_byte) +{ + uint8_t parity; + uint8_t counter_hi, counter_lo; + uint16_t counter, cycles; + // 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 PN53x Rx detection handling: + // timer stops after 5 (or 2 for PN531) bits are received + if(CHIP_DATA(pnd)->type == PN531) { + cycles -= (2 * 128); + } else { + cycles -= (5 * 128); + } + // Correction depending on last parity bit sent + parity = (last_cmd_byte >> 7) ^ ((last_cmd_byte >> 6) & 1) ^ + ((last_cmd_byte >> 5) & 1) ^ ((last_cmd_byte >> 4) & 1) ^ + ((last_cmd_byte >> 3) & 1) ^ ((last_cmd_byte >> 2) & 1) ^ + ((last_cmd_byte >> 1) & 1) ^ (last_cmd_byte & 1); + parity = parity ? 0:1; + // When sent ...YY (cmd ends with logical 1, so when last parity bit is 1): + if (parity) { + // it finishes 64us sooner than a ...ZY signal + cycles += 64; + } + // Correction depending on device design + cycles += CHIP_DATA(pnd)->timer_correction; + } + return cycles; +} + bool pn53x_initiator_transceive_bits (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) @@ -1143,11 +1193,7 @@ pn53x_initiator_transceive_bits_timed (nfc_device_t * pnd, const byte_t * pbtTx, 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; + uint8_t sz; // We can not just send bytes without parity while the PN53X expects we handled them if (!pnd->bPar) @@ -1161,11 +1207,7 @@ pn53x_initiator_transceive_bits_timed (nfc_device_t * pnd, const byte_t * pbtTx, 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); + __pn53x_init_timer(pnd); // Once timer is started, we cannot use Tama commands anymore. // E.g. on SCL3711 timer settings are reset by 0x42 InCommunicateThru command to: @@ -1187,30 +1229,10 @@ pn53x_initiator_transceive_bits_timed (nfc_device_t * pnd, const byte_t * pbtTx, 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; - } - } + // Recv corrected timer value + *cycles = __pn53x_get_timer (pnd, pbtTx[szTxBits / 8]); return true; - - } bool @@ -1262,11 +1284,7 @@ pn53x_initiator_transceive_bytes_timed (nfc_device_t * pnd, const byte_t * pbtTx 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; + uint8_t sz; // We can not just send bytes without parity while the PN53X expects we handled them if (!pnd->bPar) @@ -1280,11 +1298,7 @@ pn53x_initiator_transceive_bytes_timed (nfc_device_t * pnd, const byte_t * pbtTx 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); + __pn53x_init_timer(pnd); // Once timer is started, we cannot use Tama commands anymore. // E.g. on SCL3711 timer settings are reset by 0x42 InCommunicateThru command to: @@ -1306,26 +1320,8 @@ pn53x_initiator_transceive_bytes_timed (nfc_device_t * pnd, const byte_t * pbtTx 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; - } - } + // Recv corrected timer value + *cycles = __pn53x_get_timer (pnd, pbtTx[szTx -1]); return true; } diff --git a/libnfc/chips/pn53x.h b/libnfc/chips/pn53x.h index 4dd2186..843927e 100644 --- a/libnfc/chips/pn53x.h +++ b/libnfc/chips/pn53x.h @@ -157,10 +157,8 @@ 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; +/** Interframe timer correction */ + int16_t timer_correction; }; #define CHIP_DATA(pnd) ((struct pn53x_data*)(pnd->chip_data)) diff --git a/libnfc/drivers/acr122.c b/libnfc/drivers/acr122.c index f08f9d9..e1244a6 100644 --- a/libnfc/drivers/acr122.c +++ b/libnfc/drivers/acr122.c @@ -222,15 +222,9 @@ acr122_connect (const nfc_device_desc_t * pndd) CHIP_DATA (pnd)->state = NORMAL; CHIP_DATA (pnd)->io = &acr122_io; - - // Timer stops only after 5 bits are received => 5*128 cycles - // When sent ...ZY (cmd ends with logical 0): // 50: empirical tuning on Touchatag // 46: empirical tuning on ACR122U - CHIP_DATA (pnd)->timer_correction_zy = 50 - (5 * 128); - // When sent ...YY (cmd ends with logical 1): - // a ...ZY signal finishes 64us later than a ...YY signal - CHIP_DATA (pnd)->timer_correction_yy = CHIP_DATA (pnd)->timer_correction_zy + 64; + CHIP_DATA (pnd)->timer_correction = 50; pnd->driver = &acr122_driver; diff --git a/libnfc/drivers/arygon.c b/libnfc/drivers/arygon.c index c719695..c1e0033 100644 --- a/libnfc/drivers/arygon.c +++ b/libnfc/drivers/arygon.c @@ -174,13 +174,8 @@ arygon_connect (const nfc_device_desc_t * pndd) // The PN53x chip connected to ARYGON MCU doesn't seems to be in SLEEP mode CHIP_DATA (pnd)->state = NORMAL; CHIP_DATA (pnd)->io = &arygon_tama_io; - // Timer stops only after 5 bits are received => 5*128 cycles - // When sent ...ZY (cmd ends with logical 0): - // 46: empirical tuning - CHIP_DATA (pnd)->timer_correction_zy = 46 - (5 * 128); - // When sent ...YY (cmd ends with logical 1): - // a ...ZY signal finishes 64us later than a ...YY signal - CHIP_DATA (pnd)->timer_correction_yy = CHIP_DATA (pnd)->timer_correction_zy + 64; + // empirical tuning + CHIP_DATA (pnd)->timer_correction = 46; pnd->driver = &arygon_driver; // Check communication using "Reset TAMA" command diff --git a/libnfc/drivers/pn532_uart.c b/libnfc/drivers/pn532_uart.c index f8e7c12..a43ed93 100644 --- a/libnfc/drivers/pn532_uart.c +++ b/libnfc/drivers/pn532_uart.c @@ -160,13 +160,8 @@ pn532_uart_connect (const nfc_device_desc_t * pndd) CHIP_DATA(pnd)->type = PN532; CHIP_DATA(pnd)->state = SLEEP; CHIP_DATA(pnd)->io = &pn532_uart_io; - // Timer stops only after 5 bits are received => 5*128 cycles - // When sent ...ZY (cmd ends with logical 0): - // 48: empirical tuning - CHIP_DATA (pnd)->timer_correction_zy = 48 - (5 * 128); - // When sent ...YY (cmd ends with logical 1): - // a ...ZY signal finishes 64us later than a ...YY signal - CHIP_DATA (pnd)->timer_correction_yy = CHIP_DATA (pnd)->timer_correction_zy + 64; + // empirical tuning + CHIP_DATA(pnd)->timer_correction = 48; pnd->driver = &pn532_uart_driver; // Check communication using "Diagnose" command, with "Communication test" (0x00) diff --git a/libnfc/drivers/pn53x_usb.c b/libnfc/drivers/pn53x_usb.c index 9abe685..e0915d8 100644 --- a/libnfc/drivers/pn53x_usb.c +++ b/libnfc/drivers/pn53x_usb.c @@ -288,27 +288,19 @@ pn53x_usb_connect (const nfc_device_desc_t *pndd) CHIP_DATA (pnd)->io = &pn53x_usb_io; switch (DRIVER_DATA (pnd)->model) { + // empirical tuning case ASK_LOGO: - // Timer stops only after 5 bits are received => 5*128 cycles - // When sent ...ZY (cmd ends with logical 0): - // 50: empirical tuning - CHIP_DATA (pnd)->timer_correction_zy = 50 - (5 * 128); - // When sent ...YY (cmd ends with logical 1): - // a ...ZY signal finishes 64us later than a ...YY signal - CHIP_DATA (pnd)->timer_correction_yy = CHIP_DATA (pnd)->timer_correction_zy + 64; + CHIP_DATA (pnd)->timer_correction = 50; break; case SCM_SCL3711: case NXP_PN533: - CHIP_DATA (pnd)->timer_correction_zy = 46 - (5 * 128); - CHIP_DATA (pnd)->timer_correction_yy = CHIP_DATA (pnd)->timer_correction_zy + 64; + CHIP_DATA (pnd)->timer_correction = 46; break; case NXP_PN531: - CHIP_DATA (pnd)->timer_correction_zy = 50 - (2 * 128); - CHIP_DATA (pnd)->timer_correction_yy = CHIP_DATA (pnd)->timer_correction_zy + 64; + CHIP_DATA (pnd)->timer_correction = 50; break; case SONY_PN531: - CHIP_DATA (pnd)->timer_correction_zy = 54 - (2 * 128); - CHIP_DATA (pnd)->timer_correction_yy = CHIP_DATA (pnd)->timer_correction_zy + 64; + CHIP_DATA (pnd)->timer_correction = 54; break; default: break;