diff --git a/Firmware/Chameleon-Mini/Application/Reader14443A.c b/Firmware/Chameleon-Mini/Application/Reader14443A.c index ab00f00..78f8e78 100644 --- a/Firmware/Chameleon-Mini/Application/Reader14443A.c +++ b/Firmware/Chameleon-Mini/Application/Reader14443A.c @@ -101,9 +101,6 @@ static uint8_t CardCandidatesIdx = 0; uint16_t addParityBits(uint8_t * Buffer, uint16_t BitCount) { - uint8_t i = CardIdentificationList[0].ATQA; - if (i == 0) - return 0; if (BitCount == 7) return 7; if (BitCount % 8) @@ -473,6 +470,87 @@ uint16_t Reader14443AAppProcess(uint8_t* Buffer, uint16_t BitCount) return rVal; } + case Reader14443_Autocalibrate: + { + static enum { + RT_STATE_IDLE, + RT_STATE_SEARCHING + } RTState = RT_STATE_IDLE; + static uint8_t ErrorCount = 0; + static uint8_t Thresholds[(CODEC_THRESHOLD_CALIBRATE_MAX - CODEC_THRESHOLD_CALIBRATE_MIN) / CODEC_THRESHOLD_CALIBRATE_STEPS] = {0}; // todo this could be improved by using the bits and not the whole bytes + + if (RTState == RT_STATE_IDLE) + { + CodecThresholdSet(CODEC_THRESHOLD_CALIBRATE_MIN); + RTState = RT_STATE_SEARCHING; + ErrorCount = 0; + } else if (RTState == RT_STATE_SEARCHING && ReaderState <= STATE_HALT && ErrorCount++ == 8) { + if (CodecThresholdIncrement() >= CODEC_THRESHOLD_CALIBRATE_MAX) + { + RTState = RT_STATE_IDLE; + + bool block = false; + uint16_t min = 0; + uint16_t max = 0; + uint16_t maxdiff = 0; + uint16_t maxdiffoffset = 0; + + CommandLinePendingTaskFinished(COMMAND_INFO_OK_WITH_TEXT_ID, NULL); + uint16_t i; + for (i = 0; i < (CODEC_THRESHOLD_CALIBRATE_MAX - CODEC_THRESHOLD_CALIBRATE_MIN) / CODEC_THRESHOLD_CALIBRATE_STEPS; i++) + { + char tmpBuf[10]; + snprintf(tmpBuf, 10, "%4" PRIu16 ": ", i*CODEC_THRESHOLD_CALIBRATE_STEPS + CODEC_THRESHOLD_CALIBRATE_MIN); + TerminalSendString(tmpBuf); + if (Thresholds[i]) + { + TerminalSendStringP(PSTR("+\r\n")); + if (!block) + { + block = true; + min = i; + } + } else { + TerminalSendStringP(PSTR("-\r\n")); + if (block) + { + block = false; + max = i; + if ((max - min) > maxdiff) + { + maxdiff = max - min; + maxdiffoffset = min; + } + } + } + Thresholds[i] = 0; // reset the threshold so the next run won't show old results + } + + CodecThresholdSet((maxdiffoffset + maxdiff / 2) * CODEC_THRESHOLD_CALIBRATE_STEPS + CODEC_THRESHOLD_CALIBRATE_MIN); + + Selected = false; + Reader14443CurrentCommand = Reader14443_Do_Nothing; + CodecReaderFieldStop(); + return 0; + } + + Thresholds[(ReaderThreshold - CODEC_THRESHOLD_CALIBRATE_MIN) / CODEC_THRESHOLD_CALIBRATE_STEPS] = 0; + CodecThresholdIncrement(); + ErrorCount = 0; + } + + uint16_t rVal = Reader14443A_Select(Buffer, BitCount); + if (Selected) // we are done finding the threshold + { + Thresholds[(ReaderThreshold - CODEC_THRESHOLD_CALIBRATE_MIN) / CODEC_THRESHOLD_CALIBRATE_STEPS] = 1; + CodecThresholdIncrement(); + ReaderState = STATE_IDLE; + Reader14443ACodecStart(); + return Reader14443A_Halt(Buffer); + } + return rVal; + } + case Reader14443_Read_MF_Ultralight: { static uint8_t MFURead_CurrentAdress = 0; @@ -714,14 +792,14 @@ uint16_t Reader14443AAppProcess(uint8_t* Buffer, uint16_t BitCount) tmpBuf[size-3] = '\0'; CommandLinePendingTaskFinished(COMMAND_INFO_OK_WITH_TEXT_ID, tmpBuf); if (!enoughspace) - TerminalSendString("There is at least one more card type candidate, but there was not enough terminal buffer space.\r\n"); + TerminalSendStringP(PSTR("There is at least one more card type candidate, but there was not enough terminal buffer space.\r\n")); } // print general data - TerminalSendString("ATQA:\t"); + TerminalSendStringP(PSTR("ATQA:\t")); CommandLineAppendData(&CardCharacteristics.ATQA, 2); - TerminalSendString("UID:\t"); + TerminalSendStringP(PSTR("UID:\t")); CommandLineAppendData(CardCharacteristics.UID, CardCharacteristics.UIDSize); - TerminalSendString("SAK:\t"); + TerminalSendStringP(PSTR("SAK:\t")); CommandLineAppendData(&CardCharacteristics.SAK, 1); Reader14443CurrentCommand = Reader14443_Do_Nothing; diff --git a/Firmware/Chameleon-Mini/Application/Reader14443A.h b/Firmware/Chameleon-Mini/Application/Reader14443A.h index 63b8706..97bff8f 100644 --- a/Firmware/Chameleon-Mini/Application/Reader14443A.h +++ b/Firmware/Chameleon-Mini/Application/Reader14443A.h @@ -28,6 +28,7 @@ typedef enum { Reader14443_Send, Reader14443_Send_Raw, Reader14443_Get_UID, + Reader14443_Autocalibrate, Reader14443_Read_MF_Ultralight, Reader14443_Identify } Reader14443Command; diff --git a/Firmware/Chameleon-Mini/Codec/Codec.c b/Firmware/Chameleon-Mini/Codec/Codec.c index bb845e8..8d5b7cc 100644 --- a/Firmware/Chameleon-Mini/Codec/Codec.c +++ b/Firmware/Chameleon-Mini/Codec/Codec.c @@ -82,3 +82,22 @@ bool CodecIsReaderToBeRestarted(void) return false; } +void CodecThresholdSet(uint16_t th) +{ + ReaderThreshold = th; + DACB.CH0DATA = th; +} + +uint16_t CodecThresholdIncrement(void) +{ + ReaderThreshold += CODEC_THRESHOLD_CALIBRATE_STEPS; + DACB.CH0DATA = ReaderThreshold; + return ReaderThreshold; +} + +void CodecThresholdReset(void) +{ + ReaderThreshold = 400; + DACB.CH0DATA = ReaderThreshold; +} + diff --git a/Firmware/Chameleon-Mini/Codec/Codec.h b/Firmware/Chameleon-Mini/Codec/Codec.h index 4ac44c6..14bf6ef 100644 --- a/Firmware/Chameleon-Mini/Codec/Codec.h +++ b/Firmware/Chameleon-Mini/Codec/Codec.h @@ -73,6 +73,9 @@ #define CODEC_READER_PINCTRL_RIGHT PIN1CTRL #define CODEC_AC_DEMOD_SETTINGS AC_HSMODE_bm | AC_HYSMODE_NO_gc #define CODEC_MAXIMUM_THRESHOLD 0xFFF // the maximum voltage can be calculated with ch0data * Vref / 0xFFF +#define CODEC_THRESHOLD_CALIBRATE_MIN 128 +#define CODEC_THRESHOLD_CALIBRATE_MAX 1024 +#define CODEC_THRESHOLD_CALIBRATE_STEPS 8 #define CODEC_TIMER_TIMESTAMPS TCD1 #define CODEC_TIMER_TIMESTAMPS_CCA_VECT TCD1_CCA_vect @@ -251,4 +254,8 @@ bool CodecIsReaderFieldReady(void); void CodecReaderFieldRestart(uint16_t delay); #define FIELD_RESTART() CodecReaderFieldRestart(100) bool CodecIsReaderToBeRestarted(void); + +void CodecThresholdSet(uint16_t th); +uint16_t CodecThresholdIncrement(void); +void CodecThresholdReset(void); #endif /* CODEC_H_ */ diff --git a/Firmware/Chameleon-Mini/Terminal/CommandLine.c b/Firmware/Chameleon-Mini/Terminal/CommandLine.c index e62403b..78d5225 100644 --- a/Firmware/Chameleon-Mini/Terminal/CommandLine.c +++ b/Firmware/Chameleon-Mini/Terminal/CommandLine.c @@ -296,11 +296,18 @@ const PROGMEM CommandEntryType CommandTable[] = { .GetFunc = CommandGetThreshold }, { - .Command = COMMAND_FIELD, - .ExecFunc = NO_FUNCTION, + .Command = COMMAND_AUTOCALIBRATE, + .ExecFunc = CommandExecAutocalibrate, .ExecParamFunc = NO_FUNCTION, - .SetFunc = CommandSetField, - .GetFunc = CommandGetField + .SetFunc = NO_FUNCTION, + .GetFunc = NO_FUNCTION + }, + { + .Command = COMMAND_FIELD, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = CommandSetField, + .GetFunc = CommandGetField }, { /* This has to be last element */ .Command = COMMAND_LIST_END, diff --git a/Firmware/Chameleon-Mini/Terminal/Commands.c b/Firmware/Chameleon-Mini/Terminal/Commands.c index 84057c6..ecc63b8 100644 --- a/Firmware/Chameleon-Mini/Terminal/Commands.c +++ b/Firmware/Chameleon-Mini/Terminal/Commands.c @@ -624,3 +624,17 @@ CommandStatusIdType CommandGetField(char* OutMessage) OutMessage[1] = '\0'; return COMMAND_INFO_OK_WITH_TEXT_ID; } + + +CommandStatusIdType CommandExecAutocalibrate(char* OutMessage) +{ + if (GlobalSettings.ActiveSettingPtr->Configuration != CONFIG_ISO14443A_READER) + return COMMAND_ERR_INVALID_USAGE_ID; + ApplicationReset(); + + Reader14443CurrentCommand = Reader14443_Autocalibrate; + Reader14443AAppInit(); + Reader14443ACodecStart(); + CommandLinePendingTaskTimeout = &Reader14443AAppTimeout; + return TIMEOUT_COMMAND; +} diff --git a/Firmware/Chameleon-Mini/Terminal/Commands.h b/Firmware/Chameleon-Mini/Terminal/Commands.h index 6e2e364..744d376 100644 --- a/Firmware/Chameleon-Mini/Terminal/Commands.h +++ b/Firmware/Chameleon-Mini/Terminal/Commands.h @@ -177,6 +177,9 @@ CommandStatusIdType CommandSetTimeout(char* OutMessage, const char* InParam); CommandStatusIdType CommandGetThreshold(char* OutParam); CommandStatusIdType CommandSetThreshold(char* OutMessage, const char* InParam); +#define COMMAND_AUTOCALIBRATE "AUTOCALIBRATE" +CommandStatusIdType CommandExecAutocalibrate(char* OutMessage); + #define COMMAND_FIELD "FIELD" CommandStatusIdType CommandSetField(char* OutMessage, const char* InParam); CommandStatusIdType CommandGetField(char* OutMessage);