Basic auto calibrate for sniffing mode.

Started from the smallest threshold and when the first good threshold is obtained, stop.

May also need to extend the TIMEOUT to make this work.

Need the reader reading all the timing when sniffing in order to auto calibrate

(cherry picked from commit 2c3d5f5)
This commit is contained in:
chenzitai
2018-08-15 22:49:15 +01:00
parent 9c37cf758b
commit 86d47110a9
2 changed files with 57 additions and 47 deletions
@@ -11,7 +11,7 @@
extern bool checkParityBits(uint8_t * Buffer, uint16_t BitCount);
Sniff14443Command Sniff14443CurrentCommand = Sniff14443_Do_Nothing;
bool selected = false;
//bool selected = false;
static enum {
STATE_IDLE,
STATE_REQA,
@@ -22,16 +22,21 @@ static enum {
STATE_SAK,
} SniffState = STATE_IDLE;
static uint16_t tmp_th = CODEC_THRESHOLD_CALIBRATE_MIN;
static uint8_t Thresholds[(CODEC_THRESHOLD_CALIBRATE_MAX - CODEC_THRESHOLD_CALIBRATE_MIN) /
CODEC_THRESHOLD_CALIBRATE_STEPS] = {0};
void Sniff14443AAppInit(void){
SniffState = STATE_REQA;
selected = false;
tmp_th = CODEC_THRESHOLD_CALIBRATE_MIN;
CodecThresholdSet(tmp_th);
}
void Sniff14443AAppReset(void){
SniffState = STATE_IDLE;
Sniff14443CurrentCommand = Sniff14443_Do_Nothing;
selected = false;
}
// Currently APPTask and AppTick is not being used
void Sniff14443AAppTask(void){/* Empty */}
@@ -41,24 +46,31 @@ void Sniff14443AAppTimeout(void){
Sniff14443AAppReset();
}
void reset2REQA(void){
INLINE void reset2REQA(void){
SniffState = STATE_REQA;
LED_PORT.OUTCLR = LED_RED;
selected = false;
// TODO: Mark the current threshold as fail and continue
// Mark the current threshold as fail and continue
if(tmp_th < CODEC_THRESHOLD_CALIBRATE_MAX){
Thresholds[(tmp_th - CODEC_THRESHOLD_CALIBRATE_MIN) / CODEC_THRESHOLD_CALIBRATE_STEPS] = 0;
tmp_th = CodecThresholdIncrement();
} else{
// mark finish
}
}
uint16_t Sniff14443AAppProcess(uint8_t* Buffer, uint16_t BitCount){
switch (Sniff14443CurrentCommand){
case Sniff14443_Do_Nothing:
case Sniff14443_Do_Nothing: {
return 0;
case Sniff14443_Autocalibrate:
switch (SniffState){
}
case Sniff14443_Autocalibrate: {
switch (SniffState) {
case STATE_REQA:
LED_PORT.OUTCLR = LED_RED;
// If received Reader REQA or WUPA
if (TrafficSource == TRAFFIC_READER &&
(Buffer[0] == 0x26 || Buffer[0] == 0x54))
{
(Buffer[0] == 0x26 || Buffer[0] == 0x52)) {
SniffState = STATE_ATQA;
} else {
// Stay in this state, do noting
@@ -67,19 +79,18 @@ uint16_t Sniff14443AAppProcess(uint8_t* Buffer, uint16_t BitCount){
case STATE_ATQA:
// ATQA: P RRRR XXXX P XXRX XXXX
if (TrafficSource == TRAFFIC_CARD &&
BitCount == 2*9 &&
(Buffer[0] & 0x20) == 0x00 && // Bit6 RFU shall be 0
(Buffer[1] & 0xE0) == 0x00 && // bit13-16 RFU shall be 0
(Buffer[2] & 0x01) == 0x00 &&
checkParityBits(Buffer, BitCount))
{
BitCount == 2 * 9 &&
(Buffer[0] & 0x20) == 0x00 && // Bit6 RFU shall be 0
(Buffer[1] & 0xE0) == 0x00 && // bit13-16 RFU shall be 0
(Buffer[2] & 0x01) == 0x00 &&
checkParityBits(Buffer, BitCount)) {
// Assume this is a good ATQA
SniffState = STATE_ANTICOLLI;
} else {
// If not ATQA, but REQA, then stay on this state,
// Reset to REQA, save the counter and reset the counter
if (TrafficSource == TRAFFIC_READER &&
(Buffer[0] == 0x26 || Buffer[0] == 0x54)) {
(Buffer[0] == 0x26 || Buffer[0] == 0x52)) {
} else {
// If not ATQA and not REQA then reset to REQA
reset2REQA();
@@ -87,23 +98,21 @@ uint16_t Sniff14443AAppProcess(uint8_t* Buffer, uint16_t BitCount){
}
break;
case STATE_ANTICOLLI:
LED_PORT.OUTSET = LED_RED;
// SEL: 93/95/97
if(TrafficSource == TRAFFIC_READER &&
BitCount == 2*8 &&
(Buffer[0] & 0xf0) == 0x90 &&
(Buffer[0] & 0x09) == 0x01)
{
if (TrafficSource == TRAFFIC_READER &&
BitCount == 2 * 8 &&
(Buffer[0] & 0xf0) == 0x90 &&
(Buffer[0] & 0x09) == 0x01) {
SniffState = STATE_UID;
} else{
} else {
reset2REQA();
}
break;
case STATE_UID:
if(TrafficSource == TRAFFIC_CARD &&
BitCount == 5*9 &&
checkParityBits(Buffer, BitCount))
{
if (TrafficSource == TRAFFIC_CARD &&
BitCount == 5 * 9 &&
checkParityBits(Buffer, BitCount)) {
SniffState = STATE_SELECT;
} else {
reset2REQA();
@@ -113,36 +122,39 @@ uint16_t Sniff14443AAppProcess(uint8_t* Buffer, uint16_t BitCount){
// SELECT: 9 bytes, SEL = 93/95/97, NVB=70
if (TrafficSource == TRAFFIC_READER &&
BitCount == 9*8 &&
(Buffer[0] & 0xf0) == 0x90 &&
(Buffer[0] & 0x09) == 0x01 &&
Buffer[1] == 0x70)
{
BitCount == 9 * 8 &&
(Buffer[0] & 0xf0) == 0x90 &&
(Buffer[0] & 0x09) == 0x01 &&
Buffer[1] == 0x70) {
SniffState = STATE_SAK;
} else{
} else {
// Not valid, reset
reset2REQA();
}
break;
case STATE_SAK:
// SAK: 1Byte SAK + CRC
if(TrafficSource == TRAFFIC_CARD &&
BitCount == 3*9 &&
checkParityBits(Buffer, BitCount))
{
if((Buffer[0] & 0x04) == 0x00){
if (TrafficSource == TRAFFIC_CARD &&
BitCount == 3 * 9 &&
checkParityBits(Buffer, BitCount)) {
if ((Buffer[0] & 0x04) == 0x00) {
// UID complete, success SELECTED,
// TODO: Mark the current threshold as success and continue
// Mark the current threshold as ok and finish
// reset
SniffState = STATE_REQA;
selected = true;
LED_PORT.OUTCLR = LED_RED;
LED_PORT.OUTSET = LED_RED;
Thresholds[(tmp_th - CODEC_THRESHOLD_CALIBRATE_MIN) / CODEC_THRESHOLD_CALIBRATE_STEPS] += 1;
CommandLinePendingTaskFinished(COMMAND_INFO_OK_WITH_TEXT_ID, NULL);
char tmpBuf[10];
snprintf(tmpBuf, 10, "%4" PRIu16 ": ", tmp_th);
TerminalSendString(tmpBuf);
Sniff14443AAppReset();
} else {
// UID not complete, goto ANTICOLLI
SniffState = STATE_ANTICOLLI;
}
} else{
} else {
reset2REQA();
}
break;
@@ -150,7 +162,7 @@ uint16_t Sniff14443AAppProcess(uint8_t* Buffer, uint16_t BitCount){
break;
}
break;
}
default:
return 0;
}
@@ -281,8 +281,6 @@ INLINE void CardSniffInit(void)
* bit halves had modulations since the last pause.
*/
DACB.CH0DATA = GlobalSettings.ActiveSettingPtr->ReaderThreshold; // real threshold voltage can be calculated with ch0data * Vref / 0xFFF
// Comparator ADC
/* Configure and enable the analog comparator for finding pauses in the DEMOD signal. */
ACA.AC0CTRL = AC_HSMODE_bm | AC_HYSMODE_NO_gc | AC_INTMODE_FALLING_gc | AC_ENABLE_bm;