pn53x: factorize timer code

This commit is contained in:
Philippe Teuwen 2011-04-04 19:04:43 +00:00
parent 11668f1143
commit ffe2714b28
6 changed files with 70 additions and 100 deletions

View file

@ -1075,6 +1075,56 @@ pn53x_InJumpForDEP (nfc_device_t * pnd,
return true; 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 bool
pn53x_initiator_transceive_bits (nfc_device_t * pnd, const byte_t * pbtTx, const size_t szTxBits, 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) 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) const byte_t * pbtTxPar, byte_t * pbtRx, size_t * pszRxBits, byte_t * pbtRxPar, uint16_t * cycles)
{ {
unsigned int i; unsigned int i;
uint8_t sz, parity; uint8_t sz;
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 // We can not just send bytes without parity while the PN53X expects we handled them
if (!pnd->bPar) if (!pnd->bPar)
@ -1161,11 +1207,7 @@ pn53x_initiator_transceive_bits_timed (nfc_device_t * pnd, const byte_t * pbtTx,
if (pnd->bCrc) if (pnd->bCrc)
return false; return false;
// Initialize timer __pn53x_init_timer(pnd);
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. // Once timer is started, we cannot use Tama commands anymore.
// E.g. on SCL3711 timer settings are reset by 0x42 InCommunicateThru command to: // 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])); pn53x_read_register (pnd, REG_CIU_FIFODATA, &(pbtRx[i]));
} }
// Read timer // Recv corrected timer value
pn53x_read_register (pnd, REG_CIU_TCOUNTERVALHI, &counter_hi); *cycles = __pn53x_get_timer (pnd, pbtTx[szTxBits / 8]);
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; return true;
} }
bool bool
@ -1262,11 +1284,7 @@ pn53x_initiator_transceive_bytes_timed (nfc_device_t * pnd, const byte_t * pbtTx
size_t * pszRx, uint16_t * cycles) size_t * pszRx, uint16_t * cycles)
{ {
unsigned int i; unsigned int i;
uint8_t sz, parity; uint8_t sz;
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 // We can not just send bytes without parity while the PN53X expects we handled them
if (!pnd->bPar) if (!pnd->bPar)
@ -1280,11 +1298,7 @@ pn53x_initiator_transceive_bytes_timed (nfc_device_t * pnd, const byte_t * pbtTx
if (pnd->bCrc) if (pnd->bCrc)
return false; return false;
// Initialize timer __pn53x_init_timer(pnd);
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. // Once timer is started, we cannot use Tama commands anymore.
// E.g. on SCL3711 timer settings are reset by 0x42 InCommunicateThru command to: // 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])); pn53x_read_register (pnd, REG_CIU_FIFODATA, &(pbtRx[i]));
} }
// Read timer // Recv corrected timer value
pn53x_read_register (pnd, REG_CIU_TCOUNTERVALHI, &counter_hi); *cycles = __pn53x_get_timer (pnd, pbtTx[szTx -1]);
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; return true;
} }

View file

@ -157,10 +157,8 @@ struct pn53x_data {
uint8_t ui8Parameters; uint8_t ui8Parameters;
/** Last sent command */ /** Last sent command */
uint8_t ui8LastCommand; uint8_t ui8LastCommand;
/** Interframe correction for commands ending with logic "1" */ /** Interframe timer correction */
int16_t timer_correction_yy; int16_t timer_correction;
/** Interframe correction for commands ending with logic "0" */
int16_t timer_correction_zy;
}; };
#define CHIP_DATA(pnd) ((struct pn53x_data*)(pnd->chip_data)) #define CHIP_DATA(pnd) ((struct pn53x_data*)(pnd->chip_data))

View file

@ -222,15 +222,9 @@ acr122_connect (const nfc_device_desc_t * pndd)
CHIP_DATA (pnd)->state = NORMAL; CHIP_DATA (pnd)->state = NORMAL;
CHIP_DATA (pnd)->io = &acr122_io; 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 // 50: empirical tuning on Touchatag
// 46: empirical tuning on ACR122U // 46: empirical tuning on ACR122U
CHIP_DATA (pnd)->timer_correction_zy = 50 - (5 * 128); CHIP_DATA (pnd)->timer_correction = 50;
// 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;
pnd->driver = &acr122_driver; pnd->driver = &acr122_driver;

View file

@ -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 // The PN53x chip connected to ARYGON MCU doesn't seems to be in SLEEP mode
CHIP_DATA (pnd)->state = NORMAL; CHIP_DATA (pnd)->state = NORMAL;
CHIP_DATA (pnd)->io = &arygon_tama_io; CHIP_DATA (pnd)->io = &arygon_tama_io;
// Timer stops only after 5 bits are received => 5*128 cycles // empirical tuning
// When sent ...ZY (cmd ends with logical 0): CHIP_DATA (pnd)->timer_correction = 46;
// 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;
pnd->driver = &arygon_driver; pnd->driver = &arygon_driver;
// Check communication using "Reset TAMA" command // Check communication using "Reset TAMA" command

View file

@ -160,13 +160,8 @@ pn532_uart_connect (const nfc_device_desc_t * pndd)
CHIP_DATA(pnd)->type = PN532; CHIP_DATA(pnd)->type = PN532;
CHIP_DATA(pnd)->state = SLEEP; CHIP_DATA(pnd)->state = SLEEP;
CHIP_DATA(pnd)->io = &pn532_uart_io; CHIP_DATA(pnd)->io = &pn532_uart_io;
// Timer stops only after 5 bits are received => 5*128 cycles // empirical tuning
// When sent ...ZY (cmd ends with logical 0): CHIP_DATA(pnd)->timer_correction = 48;
// 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;
pnd->driver = &pn532_uart_driver; pnd->driver = &pn532_uart_driver;
// Check communication using "Diagnose" command, with "Communication test" (0x00) // Check communication using "Diagnose" command, with "Communication test" (0x00)

View file

@ -288,27 +288,19 @@ pn53x_usb_connect (const nfc_device_desc_t *pndd)
CHIP_DATA (pnd)->io = &pn53x_usb_io; CHIP_DATA (pnd)->io = &pn53x_usb_io;
switch (DRIVER_DATA (pnd)->model) { switch (DRIVER_DATA (pnd)->model) {
// empirical tuning
case ASK_LOGO: case ASK_LOGO:
// Timer stops only after 5 bits are received => 5*128 cycles CHIP_DATA (pnd)->timer_correction = 50;
// 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;
break; break;
case SCM_SCL3711: case SCM_SCL3711:
case NXP_PN533: case NXP_PN533:
CHIP_DATA (pnd)->timer_correction_zy = 46 - (5 * 128); CHIP_DATA (pnd)->timer_correction = 46;
CHIP_DATA (pnd)->timer_correction_yy = CHIP_DATA (pnd)->timer_correction_zy + 64;
break; break;
case NXP_PN531: case NXP_PN531:
CHIP_DATA (pnd)->timer_correction_zy = 50 - (2 * 128); CHIP_DATA (pnd)->timer_correction = 50;
CHIP_DATA (pnd)->timer_correction_yy = CHIP_DATA (pnd)->timer_correction_zy + 64;
break; break;
case SONY_PN531: case SONY_PN531:
CHIP_DATA (pnd)->timer_correction_zy = 54 - (2 * 128); CHIP_DATA (pnd)->timer_correction = 54;
CHIP_DATA (pnd)->timer_correction_yy = CHIP_DATA (pnd)->timer_correction_zy + 64;
break; break;
default: default:
break; break;