From 5f8d0ec71c046a39f53e2245e21f98c9f4de94bc Mon Sep 17 00:00:00 2001 From: cacke-r Date: Sun, 30 Jan 2022 21:20:38 +0100 Subject: [PATCH 1/9] Add Autocalibrate command to chamtool Signed-off-by: cacke-r --- Software/ChamTool/Chameleon/Device.py | 4 ++++ Software/ChamTool/chamtool.py | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/Software/ChamTool/Chameleon/Device.py b/Software/ChamTool/Chameleon/Device.py index 6aae7d57..f65ed4ec 100644 --- a/Software/ChamTool/Chameleon/Device.py +++ b/Software/ChamTool/Chameleon/Device.py @@ -27,6 +27,7 @@ class Device: COMMAND_GREEN_LED = "LEDGREEN" COMMAND_RED_LED = "LEDRED" COMMAND_THRESHOLD = "THRESHOLD" + COMMAND_AUTOCALIBRATE = "AUTOCALIBRATE" COMMAND_UPGRADE = "upgrade" STATUS_CODE_OK = 100 @@ -277,6 +278,9 @@ def cmdThreshold(self, value): else: return self.getSetCmd(self.COMMAND_THRESHOLD, value) + def cmdAutoCalibrate(self): + return self.returnCmd(self.COMMAND_AUTOCALIBRATE) + def cmdUpgrade(self): # Execute command cmdLine = self.COMMAND_UPGRADE + self.LINE_ENDING diff --git a/Software/ChamTool/chamtool.py b/Software/ChamTool/chamtool.py index 8a1203f5..a3f27e86 100755 --- a/Software/ChamTool/chamtool.py +++ b/Software/ChamTool/chamtool.py @@ -177,6 +177,18 @@ def cmdThreshold(chameleon, arg): else: return "Setting threshold failed: {}".format(arg, result['statusText']) +def cmdAutoCalibrate(chameleon, arg): + + if (len(arg) == 0): + result = chameleon.cmdAutoCalibrate() + if (result['statusCode'] in chameleon.STATUS_CODES_SUCCESS): + return "Autocalibration successfully executed {}".format(result['statusText']) + else: + return "Error during autocalibration: {}".format(result['statusText']) + + else: + return "Command failed - No Parameter expected ! {}".format(arg) + def cmdUpgrade(chameleon, arg): if(chameleon.cmdUpgrade() == 0): print ("Device changed into Upgrade Mode") @@ -223,6 +235,7 @@ def main(): cmdArgGroup.add_argument("-gl", "--gled", dest="gled", action=CmdListAction, metavar="FUNCTION", nargs='?', help="retrieve or set the current green led function") cmdArgGroup.add_argument("-rl", "--rled", dest="rled", action=CmdListAction, metavar="FUNCTION", nargs='?', help="retrieve or set the current red led function") cmdArgGroup.add_argument("-th", "--threshold", dest="threshold", action=CmdListAction, nargs='?', help="retrieve or set the threshold") + cmdArgGroup.add_argument("-ac", "--autocalibrate", dest="auto_calib", action=CmdListAction, nargs=0, help="Send AutoCalibration command") cmdArgGroup.add_argument("-ug", "--upgrade", dest="upgrade", action=CmdListAction, nargs=0, help="set the micro Controller to upgrade mode") args = argParser.parse_args() @@ -257,6 +270,7 @@ def main(): "gled" : cmdGreenLED, "rled" : cmdRedLED, "threshold" : cmdThreshold, + "auto_calib": cmdAutoCalibrate, "upgrade" : cmdUpgrade, } From 97d7ad8bf0ecc3b8364de31187471d4a506ee120 Mon Sep 17 00:00:00 2001 From: cacke-r Date: Sun, 30 Jan 2022 21:21:39 +0100 Subject: [PATCH 2/9] Hook Sniff15693 App to the AutoCalibration command Signed-off-by: cacke-r --- .../Chameleon-Mini/Application/Sniff15693.c | 22 ++++++++++++++++++- .../Chameleon-Mini/Application/Sniff15693.h | 10 ++++++++- Firmware/Chameleon-Mini/Terminal/Commands.c | 10 +++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/Sniff15693.c b/Firmware/Chameleon-Mini/Application/Sniff15693.c index 67da470e..e9a3e7ef 100644 --- a/Firmware/Chameleon-Mini/Application/Sniff15693.c +++ b/Firmware/Chameleon-Mini/Application/Sniff15693.c @@ -10,12 +10,21 @@ #include "../Codec/SniffISO15693.h" #include "Sniff15693.h" +Sniff15693Command Sniff15693CurrentCommand; + +void SniffISO15693AppTimeout(void) +{ + SniffISO15693AppReset(); +} + void SniffISO15693AppInit(void) { + Sniff15693CurrentCommand = Sniff15693_Do_Nothing; } void SniffISO15693AppReset(void) { + SniffISO15693AppInit(); } @@ -27,11 +36,22 @@ void SniffISO15693AppTask(void) void SniffISO15693AppTick(void) { - } uint16_t SniffISO15693AppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) { + char str[64]; + switch (Sniff15693CurrentCommand) { + case Sniff15693_Do_Nothing: { + return 0; + } + case Sniff15693_Autocalibrate: { + sprintf(str, "CMD: Sniff15693_Autocalibrate "); + LogEntry(LOG_INFO_GENERIC, str, strlen(str)); + CommandLinePendingTaskFinished(COMMAND_INFO_FALSE_ID, NULL); + return 0; + } + } return 0; } diff --git a/Firmware/Chameleon-Mini/Application/Sniff15693.h b/Firmware/Chameleon-Mini/Application/Sniff15693.h index 46920d9c..f809a67c 100644 --- a/Firmware/Chameleon-Mini/Application/Sniff15693.h +++ b/Firmware/Chameleon-Mini/Application/Sniff15693.h @@ -1,5 +1,5 @@ /* - * SniffISO15693.h + * Sniff15693.h * * Created on: 05.11.2019 * Author: ceres-c @@ -16,5 +16,13 @@ void SniffISO15693AppReset(void); void SniffISO15693AppTask(void); void SniffISO15693AppTick(void); uint16_t SniffISO15693AppProcess(uint8_t* FrameBuf, uint16_t FrameBytes); +void SniffISO15693AppTimeout(void); + +typedef enum { + Sniff15693_Do_Nothing, + Sniff15693_Autocalibrate, +} Sniff15693Command; + +extern Sniff15693Command Sniff15693CurrentCommand; #endif /* SNIFF_15693_H_ */ diff --git a/Firmware/Chameleon-Mini/Terminal/Commands.c b/Firmware/Chameleon-Mini/Terminal/Commands.c index 9ee1b3b0..c3da96c6 100644 --- a/Firmware/Chameleon-Mini/Terminal/Commands.c +++ b/Firmware/Chameleon-Mini/Terminal/Commands.c @@ -16,6 +16,7 @@ #include "../Battery.h" #include "../Codec/Codec.h" #include "../Application/Reader14443A.h" +#include "../Application/Sniff15693.h" extern Reader14443Command Reader14443CurrentCommand; extern Sniff14443Command Sniff14443CurrentCommand; @@ -655,6 +656,15 @@ CommandStatusIdType CommandExecAutocalibrate(char *OutMessage) { CommandLinePendingTaskTimeout = &Sniff14443AAppTimeout; return TIMEOUT_COMMAND; } +#endif +#ifdef CONFIG_ISO15693_SNIFF_SUPPORT + if (GlobalSettings.ActiveSettingPtr->Configuration == CONFIG_ISO15693_SNIFF) { + ApplicationReset(); + + Sniff15693CurrentCommand = Sniff15693_Autocalibrate; + CommandLinePendingTaskTimeout = &SniffISO15693AppTimeout; + return TIMEOUT_COMMAND; + } #endif return COMMAND_ERR_INVALID_USAGE_ID; } From 821de780abe4b6db1e76cf1cf5cbe5cbe73be289 Mon Sep 17 00:00:00 2001 From: cacke-r Date: Tue, 15 Feb 2022 20:00:22 +0100 Subject: [PATCH 3/9] SniffISO15693: Add functions to codec to enable autocalibration Signed-off-by: cacke-r --- Firmware/Chameleon-Mini/Codec/SniffISO15693.c | 62 ++++++++++++++++--- Firmware/Chameleon-Mini/Codec/SniffISO15693.h | 12 ++++ 2 files changed, 64 insertions(+), 10 deletions(-) diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO15693.c b/Firmware/Chameleon-Mini/Codec/SniffISO15693.c index ef8ec4ff..60026db0 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO15693.c +++ b/Firmware/Chameleon-Mini/Codec/SniffISO15693.c @@ -52,6 +52,7 @@ static volatile uint8_t ReaderByteCount; static volatile uint8_t CardByteCount; static volatile uint16_t SampleDataCount; static volatile uint8_t bBrokenFrame; +static bool bAutoThreshold = true; ///////////////////////////////////////////////// // VCD->VICC @@ -272,6 +273,20 @@ INLINE void SNIFF_ISO15693_READER_EOC_VCD(void) { // VICC->VCD ///////////////////////////////////////////////// + +/* Inline function to set the threshold, if bAutoThreshold is enabled*/ +INLINE void SetDacCh0Data(uint16_t ch0data){ + /* TODO: Check if either of the branches can be avoided */ + /* to optimize the performance */ + if(bAutoThreshold){ + if (ch0data < 0xFFF) + DACB.CH0DATA = ch0data; + else + DACB.CH0DATA = 0xFFF; + } + return; +} + /* Initialize card sniffing options Note: Currently implemented only single subcarrier SOC detection */ @@ -394,8 +409,8 @@ INLINE void CardSniffInit(void) { ADCA.EVCTRL = ADC_SWEEP_01_gc; /* Write threshold to the DAC channel 0 (connected to Analog Comparator positive input) */ - DACB.CH0DATA = DemodFloorNoiseLevel + (DemodFloorNoiseLevel >> 3); /* Slightly increase DAC output to ease triggering */ - DACB.CH0DATA |= -( (DACB.CH0DATA & 0xFFF) < DemodFloorNoiseLevel); /* Branchfree saturating addition */ + SetDacCh0Data(DemodFloorNoiseLevel + (DemodFloorNoiseLevel >> 3)); /* Slightly increase DAC output to ease triggering */ + /** * Finally, now that we have the DAC set up, configure analog comparator A (the only one in this MCU) @@ -449,8 +464,8 @@ ISR_SHARED isr_SNIFF_ISO15693_ACA_AC0_VECT(void) { ACA.AC0CTRL = AC_ENABLE_bm | AC_HSMODE_bm | AC_HYSMODE_LARGE_gc | AC_INTMODE_RISING_gc | AC_INTLVL_OFF_gc; /* Disable this interrupt */ - DACB.CH0DATA = DemodFloorNoiseLevel + (DemodFloorNoiseLevel >> 2); /* Blindly increase threshold after 1 pulse */ - DACB.CH0DATA |= -( (DACB.CH0DATA & 0xFFF) < DemodFloorNoiseLevel); /* Branchfree saturating addition */ + SetDacCh0Data(DemodFloorNoiseLevel + (DemodFloorNoiseLevel >> 2)); /* Blindly increase threshold after 1 pulse */ + /* Note: by the time the DAC has changed its output, we're already after the 2nd pulse */ } @@ -460,9 +475,8 @@ ISR_SHARED isr_SNIFF_ISO15693_ACA_AC0_VECT(void) { ISR_SHARED isr_SNIFF_ISO15693_CODEC_TIMER_TIMESTAMPS_CCA_VECT(void) { uint16_t TempRead = ADCA.CH1RES; /* Can't possibly be greater than 0xFFF since the dac has 12 bit res */ - DACB.CH0DATA = TempRead - ANTENNA_LEVEL_OFFSET; /* Further increase DAC output after 3 pulses with value from PORTA Pin 2 (DEMOD-READER/2.3) */ - DACB.CH0DATA &= -(DACB.CH0DATA <= TempRead); /* Branchfree saturating subtraction */ + SetDacCh0Data(TempRead - ANTENNA_LEVEL_OFFSET); /* Further increase DAC output after 3 pulses with value from PORTA Pin 2 (DEMOD-READER/2.3) */ CODEC_TIMER_TIMESTAMPS.INTCTRLB = TC_CCAINTLVL_OFF_gc; /* Disable this interrupt */ } @@ -480,8 +494,8 @@ ISR_SHARED isr_SNIFF_ISO15693_CODEC_TIMER_LOADMOD_CCA_VECT(void) { CODEC_TIMER_LOADMOD.INTCTRLB = TC_CCAINTLVL_OFF_gc; /* Disable all compare interrupts, including this one */ - DACB.CH0DATA = DemodFloorNoiseLevel + (DemodFloorNoiseLevel >> 3); /* Restore DAC output (AC negative comparation threshold) to pre-AC0 interrupt update value */ - DACB.CH0DATA |= -( (DACB.CH0DATA & 0xFFF) < DemodFloorNoiseLevel); /* Branchfree saturating addition */ + SetDacCh0Data(DemodFloorNoiseLevel + (DemodFloorNoiseLevel >> 3)); /* Restore DAC output (AC negative comparation threshold) to pre-AC0 interrupt update value */ + ACA.AC0CTRL |= AC_INTLVL_HI_gc; /* Re-enable analog comparator interrupt to search for another pulse */ CODEC_TIMER_TIMESTAMPS.INTCTRLB = TC_CCAINTLVL_HI_gc; /* Re enable CCA interrupt in case it was triggered and then is now disabled */ @@ -564,8 +578,8 @@ ISR_SHARED isr_SNIFF_ISO15693_CODEC_TIMER_LOADMOD_OVF_VECT(void) { /* No SOC. The train of pulses was actually garbage. */ /* Restore DAC output to intial value */ - DACB.CH0DATA = DemodFloorNoiseLevel + (DemodFloorNoiseLevel >> 3); - DACB.CH0DATA |= -( (DACB.CH0DATA & 0xFFF) < DemodFloorNoiseLevel); /* Branchfree saturating addition */ + SetDacCh0Data(DemodFloorNoiseLevel + (DemodFloorNoiseLevel >> 3)); + /* Re enable AC interrupt */ ACA.AC0CTRL = AC_ENABLE_bm | AC_HSMODE_bm | AC_HYSMODE_LARGE_gc | AC_INTMODE_RISING_gc | AC_INTLVL_HI_gc; @@ -692,6 +706,34 @@ void SniffISO15693CodecInit(void) { ReaderSniffInit(); } +/************************************************************ + Function used by the Terminal command to display (GET) + the state of the Autothreshold Feature. +************************************************************/ +bool SniffISO15693GetAutoThreshold(void){ + return bAutoThreshold; +} + +/************************************************************ + Function used by the Application level to disable the + Autothreshold Feature. + If it is disabled: The threshold will be taken from + GlobalSettings.ActiveSettingPtr->ReaderThreshold +************************************************************/ +void SniffISO15693CtrlAutoThreshold(bool enable){ + bAutoThreshold = enable; + return; +} + +/************************************************************ + Function used by the Application level to get the FloorNoise + FloorNoise can be used to define the scanning range for the + Autocalibration. +************************************************************/ +uint16_t SniffISO15693GetFloorNoise(void){ + return DemodFloorNoiseLevel; +} + void SniffISO15693CodecDeInit(void) { /* Gracefully shutdown codec */ CODEC_DEMOD_IN_PORT.INT0MASK = 0; diff --git a/Firmware/Chameleon-Mini/Codec/SniffISO15693.h b/Firmware/Chameleon-Mini/Codec/SniffISO15693.h index ef7d1d2c..c623bf9d 100644 --- a/Firmware/Chameleon-Mini/Codec/SniffISO15693.h +++ b/Firmware/Chameleon-Mini/Codec/SniffISO15693.h @@ -32,6 +32,18 @@ void SniffISO15693CodecTask(void); /* Application Interface */ void SniffISO15693CodecStart(void); void SniffISO15693CodecReset(void); +/* Can be used by an application to disable */ +/* The auto-threshold algorithm */ +/* This is needed in corner cases - where the algo doesnt */ +/* find a proper threshold */ +/* In this case, the application can run an autocalibration session */ +void SniffISO15693CtrlAutoThreshold(bool enable); +bool SniffISO15693GetAutoThreshold(void); + +/* Function is used to receive the measured FloorNoise */ +/* This is used to narrow down the range, which is considered for */ +/* Threshold */ +uint16_t SniffISO15693GetFloorNoise(void); /* Internal functions */ INLINE void SNIFF_ISO15693_READER_EOC_VCD(void); From ad1643482a0c478ee8415927721607d963a585e7 Mon Sep 17 00:00:00 2001 From: cacke-r Date: Tue, 15 Feb 2022 20:07:25 +0100 Subject: [PATCH 4/9] Sniff15693: Implementation of Autocalibration command Signed-off-by: cacke-r --- .../Chameleon-Mini/Application/Sniff15693.c | 180 +++++++++++++++++- 1 file changed, 177 insertions(+), 3 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/Sniff15693.c b/Firmware/Chameleon-Mini/Application/Sniff15693.c index e9a3e7ef..64584f3d 100644 --- a/Firmware/Chameleon-Mini/Application/Sniff15693.c +++ b/Firmware/Chameleon-Mini/Application/Sniff15693.c @@ -10,7 +10,58 @@ #include "../Codec/SniffISO15693.h" #include "Sniff15693.h" +/* Incrementing in steps of 50 was considered as sufficiently */ +/* accurate during tests */ +#define ISO15693_TH_CALIBRATE_STEPS 50 +//#define ISO15693_DEBUG_LOG +typedef enum { + AUTOCALIB_INIT, + AUTOCALIB_READER_DATA, + AUTOCALIB_CARD_DATA, +} Sniff15693State; + Sniff15693Command Sniff15693CurrentCommand; +static Sniff15693State autocalib_state = AUTOCALIB_INIT; + +/* The Autocalib shall work as following: */ +/* Calls to AppProcess shall always alternate b/w ReaderData and CardData */ +/* If there are 2 successive calls to to AppProcess with ReaderData, it means */ +/* we have not received card data -> bad case */ +/* So, we need always two calls to AppProcess to evaluate b/w good & bad case */ +/* two calls are called a cycle further on */ +/* we do increment the threshold after each cycle */ +/* We store the first successfull card data as min_succ_th (means the threshold when we have received */ +/* card data the first time */ +/* And now we increment the threshold further, until we dont get card data anymore */ +/* This will be stored in 'max_succ_th */ +/* We do assume now, that the optimal threshold is between min_succ_th and max_succ_th */ +/* With this approach we do avoid, to maintain a large array of possible thresholds */ +/* The serach range is defined by the DemodFloorNoiseLevel */ +/* We search b/w: */ +/* 0.5 * DemodFloorNoiseLevel --> 1.5 * DemodFloorNoiseLevel */ + + +/* + _________________________ scanning range ______________________________________ + / \ + -|---------|-----------------------------------------threshold-----------------------------|------------> + | | +typical pattern| | +- bad case |------------------------+-++++-+-+---------------------------------------------| ++ good case | | | | + | min_succ_th | | + | max_succ_th | + min_th max_th + + And finally the desired threshold is: (min_succ_th + max_succ_th) >> 1 +*/ +static uint16_t curr_th = 0; +static uint16_t min_th = 0; +static uint16_t max_th = 0xFFF; +static uint16_t min_succ_th = 0; +static uint16_t max_succ_th = 0xFFF; + +static bool last_cycle_successful = false; void SniffISO15693AppTimeout(void) { @@ -20,6 +71,7 @@ void SniffISO15693AppTimeout(void) void SniffISO15693AppInit(void) { Sniff15693CurrentCommand = Sniff15693_Do_Nothing; + autocalib_state = AUTOCALIB_INIT; } void SniffISO15693AppReset(void) @@ -38,17 +90,139 @@ void SniffISO15693AppTick(void) } +INLINE void SniffISO15693InitAutocalib(void){ + uint16_t floor_noise = SniffISO15693GetFloorNoise(); + /* We search b/w: */ + /* 0.5 * DemodFloorNoiseLevel --> 1.5 * DemodFloorNoiseLevel */ + min_th = floor_noise >> 1; + max_th = floor_noise + (floor_noise >> 1); + if(min_th >= max_th) { + min_th = 0; + max_th = 0xFFF; + } + + min_succ_th = 0; + max_succ_th = 0xFFF; + + last_cycle_successful = false; +#ifdef ISO15693_DEBUG_LOG + { + char str[64]; + sprintf(str, "Sniff15693: Start Autocalibration %d - %d ", min_th, max_th); + LogEntry(LOG_INFO_GENERIC, str, strlen(str)); + } +#endif /*#ifdef ISO15693_DEBUG_LOG*/ + curr_th = min_th; + CodecThresholdSet(curr_th); + return; +} + +INLINE void SniffISO15693FinishAutocalib(void){ + uint16_t new_th; + new_th = (min_succ_th + max_succ_th) >> 1; + CodecThresholdSet(new_th); +#ifdef ISO15693_DEBUG_LOG + { + char str[64]; + sprintf(str, "Sniff15693: Finished Autocalibration %d - %d --> % d", min_succ_th, max_succ_th, new_th); + LogEntry(LOG_INFO_GENERIC, str, strlen(str)); + } +#endif /*#ifdef ISO15693_DEBUG_LOG*/ + SniffISO15693AppInit(); + CommandLinePendingTaskFinished(COMMAND_INFO_OK_WITH_TEXT_ID, NULL); + //CommandLinePendingTaskFinished(COMMAND_INFO_FALSE_ID, NULL); +} + +INLINE void SniffISO15693IncrementThreshold(void){ + + /* So increment the threshold */ + /* Steps of 3*16=48 are sufficient for us */ + curr_th += ISO15693_TH_CALIBRATE_STEPS; + CodecThresholdSet(curr_th); +#ifdef ISO15693_DEBUG_LOG + { + char str[64]; + sprintf(str, "Sniff15693: Try next th=%d", curr_th); + LogEntry(LOG_INFO_GENERIC, str, strlen(str)); + } +#endif /*#ifdef ISO15693_DEBUG_LOG*/ + if(curr_th >= max_th) { + /* We are finished now */ + /* Evaluate the results */ + SniffISO15693FinishAutocalib(); + } +} + uint16_t SniffISO15693AppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) { +#ifdef ISO15693_DEBUG_LOG char str[64]; +#endif switch (Sniff15693CurrentCommand) { case Sniff15693_Do_Nothing: { return 0; } case Sniff15693_Autocalibrate: { - sprintf(str, "CMD: Sniff15693_Autocalibrate "); - LogEntry(LOG_INFO_GENERIC, str, strlen(str)); - CommandLinePendingTaskFinished(COMMAND_INFO_FALSE_ID, NULL); + switch(autocalib_state){ + case(AUTOCALIB_INIT): + SniffISO15693InitAutocalib(); + if(SniffTrafficSource == TRAFFIC_CARD) + autocalib_state = AUTOCALIB_CARD_DATA; + else + autocalib_state = AUTOCALIB_READER_DATA; + break; + case(AUTOCALIB_READER_DATA): /* Means last time we have received reader data */ + if(SniffTrafficSource == TRAFFIC_READER){ + /* Second time Reader Data received */ + /* This means no card data received */ + /* If we had successful tries before */ + /* we need to record it as threshold max here */ + if(last_cycle_successful == true){ + max_succ_th = GlobalSettings.ActiveSettingPtr->ReaderThreshold - + CODEC_THRESHOLD_CALIBRATE_STEPS; +#ifdef ISO15693_DEBUG_LOG + sprintf(str, "Sniff15693: Updated max_succ_th (%d) ", max_succ_th); + LogEntry(LOG_INFO_GENERIC, str, strlen(str)); +#endif /*#ifdef ISO15693_DEBUG_LOG*/ + } + last_cycle_successful = false; + }else{ + /* We have received card data now */ + /* Threshold is in a good range */ + /* if min_succ_th was never set ( == 0) */ + /* Set it now to the current threshold */ + if (min_succ_th == 0) + min_succ_th = GlobalSettings.ActiveSettingPtr->ReaderThreshold; + last_cycle_successful = true; +#ifdef ISO15693_DEBUG_LOG + sprintf(str, "Sniff15693: Found card data (%d) ", min_succ_th); + LogEntry(LOG_INFO_GENERIC, str, strlen(str)); +#endif /*#ifdef ISO15693_DEBUG_LOG*/ + autocalib_state = AUTOCALIB_CARD_DATA; + } + SniffISO15693IncrementThreshold(); + break; + case(AUTOCALIB_CARD_DATA): /* Means last time we have received card data */ + if(SniffTrafficSource == TRAFFIC_CARD){ + /* We have received card data now */ + /* Threshold is in a good range */ + /* if min_succ_th was never set ( == 0) */ + /* Set it now to the current threshold */ + if (min_succ_th == 0) + min_succ_th = GlobalSettings.ActiveSettingPtr->ReaderThreshold; + last_cycle_successful = true; +#ifdef ISO15693_DEBUG_LOG + sprintf(str, "Sniff15693: Found card data (%d) ", min_succ_th); + LogEntry(LOG_INFO_GENERIC, str, strlen(str)); +#endif /*#ifdef ISO15693_DEBUG_LOG*/ + SniffISO15693IncrementThreshold(); + }else{ + autocalib_state = AUTOCALIB_READER_DATA; + } + break; + default: + break; + } return 0; } } From b04351b1afa002166cdba3c8f51e76f3b866e247 Mon Sep 17 00:00:00 2001 From: cacke-r Date: Wed, 9 Feb 2022 21:46:30 +0100 Subject: [PATCH 5/9] Sniff15693: Add CRC Check on received data Signed-off-by: cacke-r --- .../Chameleon-Mini/Application/Sniff15693.c | 44 ++++++++++++------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/Sniff15693.c b/Firmware/Chameleon-Mini/Application/Sniff15693.c index 64584f3d..cf4f87a3 100644 --- a/Firmware/Chameleon-Mini/Application/Sniff15693.c +++ b/Firmware/Chameleon-Mini/Application/Sniff15693.c @@ -155,9 +155,15 @@ INLINE void SniffISO15693IncrementThreshold(void){ uint16_t SniffISO15693AppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) { + + bool crc_chk = ISO15693CheckCRC(FrameBuf, FrameBytes-ISO15693_CRC16_SIZE); + #ifdef ISO15693_DEBUG_LOG char str[64]; -#endif + sprintf(str, "Sniff15693: CrcCheck result=%d", crc_chk); + LogEntry(LOG_INFO_GENERIC, str, strlen(str)); +#endif /*#ifdef ISO15693_DEBUG_LOG*/ + switch (Sniff15693CurrentCommand) { case Sniff15693_Do_Nothing: { return 0; @@ -187,15 +193,17 @@ uint16_t SniffISO15693AppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) } last_cycle_successful = false; }else{ - /* We have received card data now */ - /* Threshold is in a good range */ - /* if min_succ_th was never set ( == 0) */ - /* Set it now to the current threshold */ - if (min_succ_th == 0) - min_succ_th = GlobalSettings.ActiveSettingPtr->ReaderThreshold; - last_cycle_successful = true; + if (crc_chk){ + /* We have received card data now */ + /* Threshold is in a good range */ + /* if min_succ_th was never set ( == 0) */ + /* Set it now to the current threshold */ + if (min_succ_th == 0) + min_succ_th = GlobalSettings.ActiveSettingPtr->ReaderThreshold; + last_cycle_successful = true; + } #ifdef ISO15693_DEBUG_LOG - sprintf(str, "Sniff15693: Found card data (%d) ", min_succ_th); + sprintf(str, "Sniff15693: Found card data (%d) - crc=%d", min_succ_th, crc_chk); LogEntry(LOG_INFO_GENERIC, str, strlen(str)); #endif /*#ifdef ISO15693_DEBUG_LOG*/ autocalib_state = AUTOCALIB_CARD_DATA; @@ -204,15 +212,17 @@ uint16_t SniffISO15693AppProcess(uint8_t* FrameBuf, uint16_t FrameBytes) break; case(AUTOCALIB_CARD_DATA): /* Means last time we have received card data */ if(SniffTrafficSource == TRAFFIC_CARD){ - /* We have received card data now */ - /* Threshold is in a good range */ - /* if min_succ_th was never set ( == 0) */ - /* Set it now to the current threshold */ - if (min_succ_th == 0) - min_succ_th = GlobalSettings.ActiveSettingPtr->ReaderThreshold; - last_cycle_successful = true; + if (crc_chk){ + /* We have received card data now */ + /* Threshold is in a good range */ + /* if min_succ_th was never set ( == 0) */ + /* Set it now to the current threshold */ + if (min_succ_th == 0) + min_succ_th = GlobalSettings.ActiveSettingPtr->ReaderThreshold; + last_cycle_successful = true; + } #ifdef ISO15693_DEBUG_LOG - sprintf(str, "Sniff15693: Found card data (%d) ", min_succ_th); + sprintf(str, "Sniff15693: Found card data (%d) - crc=%d", min_succ_th, crc_chk); LogEntry(LOG_INFO_GENERIC, str, strlen(str)); #endif /*#ifdef ISO15693_DEBUG_LOG*/ SniffISO15693IncrementThreshold(); From b8fec22458281a4395b0df505b5689dbaa4d2987 Mon Sep 17 00:00:00 2001 From: cacke-r Date: Mon, 14 Feb 2022 21:01:46 +0100 Subject: [PATCH 6/9] Terminal: Add commands to control Sniff15693 autothreshold feature Signed-off-by: cacke-r --- .../Chameleon-Mini/Terminal/CommandLine.c | 9 ++++ Firmware/Chameleon-Mini/Terminal/Commands.c | 46 +++++++++++++++++++ Firmware/Chameleon-Mini/Terminal/Commands.h | 6 +++ 3 files changed, 61 insertions(+) diff --git a/Firmware/Chameleon-Mini/Terminal/CommandLine.c b/Firmware/Chameleon-Mini/Terminal/CommandLine.c index f538dddb..254e4504 100644 --- a/Firmware/Chameleon-Mini/Terminal/CommandLine.c +++ b/Firmware/Chameleon-Mini/Terminal/CommandLine.c @@ -334,6 +334,15 @@ const PROGMEM CommandEntryType CommandTable[] = { .GetFunc = NO_FUNCTION }, #endif +#ifdef CONFIG_ISO15693_SNIFF_SUPPORT + { + .Command = COMMAND_AUTOTHRESHOLD, + .ExecFunc = NO_FUNCTION, + .ExecParamFunc = NO_FUNCTION, + .SetFunc = CommandSetAutoThreshold, + .GetFunc = CommandGetAutoThreshold + }, +#endif #ifdef ENABLE_RUNTESTS_TERMINAL_COMMAND #include "../Tests/ChameleonTerminalInclude.c" #endif diff --git a/Firmware/Chameleon-Mini/Terminal/Commands.c b/Firmware/Chameleon-Mini/Terminal/Commands.c index c3da96c6..68f4b0bf 100644 --- a/Firmware/Chameleon-Mini/Terminal/Commands.c +++ b/Firmware/Chameleon-Mini/Terminal/Commands.c @@ -18,6 +18,9 @@ #include "../Application/Reader14443A.h" #include "../Application/Sniff15693.h" +#ifdef CONFIG_ISO15693_SNIFF_SUPPORT +#include "../Codec/SniffISO15693.h" +#endif /*#ifdef CONFIG_ISO15693_SNIFF_SUPPORT*/ extern Reader14443Command Reader14443CurrentCommand; extern Sniff14443Command Sniff14443CurrentCommand; @@ -687,3 +690,46 @@ CommandStatusIdType CommandExecClone(char *OutMessage) { #endif } #endif + +#ifdef CONFIG_ISO15693_SNIFF_SUPPORT +CommandStatusIdType CommandGetAutoThreshold(char *OutParam){ + + /* Only Execute the command if the current configuration is CONFIG_ISO15693_SNIFF */ + if (GlobalSettings.ActiveSettingPtr->Configuration != CONFIG_ISO15693_SNIFF) + return COMMAND_ERR_INVALID_USAGE_ID; + + /* Get Autothreshold mode */ + if(SniffISO15693GetAutoThreshold()) + snprintf(OutParam, TERMINAL_BUFFER_SIZE, "%c (enabled)", COMMAND_CHAR_TRUE); + else + snprintf(OutParam, TERMINAL_BUFFER_SIZE, "%c - (disabled)", COMMAND_CHAR_FALSE); + /* In case of overflow, snprintf does not write the terminating '\0' */ + /* so we should make sure it gets terminated */ + OutParam[TERMINAL_BUFFER_SIZE-1] = '\0'; + + return COMMAND_INFO_OK_WITH_TEXT_ID; +} + +CommandStatusIdType CommandSetAutoThreshold(char *OutMessage, const char *InParam){ + + /* Only Execute the command if the current configuration is CONFIG_ISO15693_SNIFF */ + if (GlobalSettings.ActiveSettingPtr->Configuration != CONFIG_ISO15693_SNIFF) + return COMMAND_ERR_INVALID_USAGE_ID; + + if (COMMAND_IS_SUGGEST_STRING(InParam)) { + snprintf(OutMessage, TERMINAL_BUFFER_SIZE, "%c (enable), %c (disable)", COMMAND_CHAR_TRUE, COMMAND_CHAR_FALSE); + /* In case of overflow, snprintf does not write the terminating '\0' */ + /* so we should make sure it gets terminated */ + OutMessage[TERMINAL_BUFFER_SIZE-1] = '\0'; + return COMMAND_INFO_OK_WITH_TEXT_ID; + } else if (InParam[0] == COMMAND_CHAR_TRUE) { + SniffISO15693CtrlAutoThreshold(true); + return COMMAND_INFO_OK_ID; + } else if (InParam[0] == COMMAND_CHAR_FALSE) { + SniffISO15693CtrlAutoThreshold(false); + return COMMAND_INFO_OK_ID; + } else { + return COMMAND_ERR_INVALID_PARAM_ID; + } +} +#endif /*#ifdef CONFIG_ISO15693_SNIFF_SUPPORT*/ diff --git a/Firmware/Chameleon-Mini/Terminal/Commands.h b/Firmware/Chameleon-Mini/Terminal/Commands.h index 6f6364b8..fd5e4dc1 100644 --- a/Firmware/Chameleon-Mini/Terminal/Commands.h +++ b/Firmware/Chameleon-Mini/Terminal/Commands.h @@ -194,6 +194,12 @@ CommandStatusIdType CommandGetField(char *OutMessage); #define COMMAND_CLONE "CLONE" CommandStatusIdType CommandExecClone(char *OutMessage); +#ifdef CONFIG_ISO15693_SNIFF_SUPPORT +#define COMMAND_AUTOTHRESHOLD "AUTOTHRESHOLD" +CommandStatusIdType CommandGetAutoThreshold(char *OutParam); +CommandStatusIdType CommandSetAutoThreshold(char *OutMessage, const char *InParam); +#endif /*#ifdef CONFIG_ISO15693_SNIFF_SUPPORT*/ + #ifdef ENABLE_RUNTESTS_TERMINAL_COMMAND #include "../Tests/ChameleonTerminal.h" #endif From c68604002dbc9eea2af99fddc4e413d1706cabd4 Mon Sep 17 00:00:00 2001 From: cacke-r Date: Tue, 15 Feb 2022 20:15:15 +0100 Subject: [PATCH 7/9] Commands: Autocalibrate: Dont execute if ISO15693 codec uses autothreshold Signed-off-by: cacke-r --- Firmware/Chameleon-Mini/Terminal/Commands.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Firmware/Chameleon-Mini/Terminal/Commands.c b/Firmware/Chameleon-Mini/Terminal/Commands.c index 68f4b0bf..78f8a156 100644 --- a/Firmware/Chameleon-Mini/Terminal/Commands.c +++ b/Firmware/Chameleon-Mini/Terminal/Commands.c @@ -661,7 +661,10 @@ CommandStatusIdType CommandExecAutocalibrate(char *OutMessage) { } #endif #ifdef CONFIG_ISO15693_SNIFF_SUPPORT - if (GlobalSettings.ActiveSettingPtr->Configuration == CONFIG_ISO15693_SNIFF) { + /* Only execute autocalibration if the codec does not use autothreshold */ + /* It needs to be disabled by the AUTOTHRESHOLD=DISABLE command */ + if ((GlobalSettings.ActiveSettingPtr->Configuration == CONFIG_ISO15693_SNIFF) && + (SniffISO15693GetAutoThreshold() == false)){ ApplicationReset(); Sniff15693CurrentCommand = Sniff15693_Autocalibrate; From a212bbb313e89662c93dceea6080899c7b58973b Mon Sep 17 00:00:00 2001 From: cacke-r Date: Tue, 15 Feb 2022 20:56:36 +0100 Subject: [PATCH 8/9] Chamtool: Add Autothreshold command Signed-off-by: cacke-r --- Software/ChamTool/Chameleon/Device.py | 6 +++++- Software/ChamTool/chamtool.py | 13 +++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/Software/ChamTool/Chameleon/Device.py b/Software/ChamTool/Chameleon/Device.py index f65ed4ec..e050db8c 100644 --- a/Software/ChamTool/Chameleon/Device.py +++ b/Software/ChamTool/Chameleon/Device.py @@ -28,6 +28,7 @@ class Device: COMMAND_RED_LED = "LEDRED" COMMAND_THRESHOLD = "THRESHOLD" COMMAND_AUTOCALIBRATE = "AUTOCALIBRATE" + COMMAND_AUTOTHRESHOLD = "AUTOTHRESHOLD" COMMAND_UPGRADE = "upgrade" STATUS_CODE_OK = 100 @@ -280,7 +281,10 @@ def cmdThreshold(self, value): def cmdAutoCalibrate(self): return self.returnCmd(self.COMMAND_AUTOCALIBRATE) - + + def cmdAutoThreshold(self, newLogMode): + return self.getSetCmd(self.COMMAND_AUTOTHRESHOLD, newLogMode) + def cmdUpgrade(self): # Execute command cmdLine = self.COMMAND_UPGRADE + self.LINE_ENDING diff --git a/Software/ChamTool/chamtool.py b/Software/ChamTool/chamtool.py index a3f27e86..95bae741 100755 --- a/Software/ChamTool/chamtool.py +++ b/Software/ChamTool/chamtool.py @@ -188,6 +188,17 @@ def cmdAutoCalibrate(chameleon, arg): else: return "Command failed - No Parameter expected ! {}".format(arg) + +def cmdAutoThreshold(chameleon, arg): + result = chameleon.cmdAutoThreshold(arg) + + if (arg is None): + return "Autothreshold is: {}".format(result['response']) + else: + if (result['statusCode'] in chameleon.STATUS_CODES_SUCCESS): + return "Autothreshold is now {}".format(arg) + else: + return "Setting Autothreshold failed: {}".format(arg, result['statusText']) def cmdUpgrade(chameleon, arg): if(chameleon.cmdUpgrade() == 0): @@ -236,6 +247,7 @@ def main(): cmdArgGroup.add_argument("-rl", "--rled", dest="rled", action=CmdListAction, metavar="FUNCTION", nargs='?', help="retrieve or set the current red led function") cmdArgGroup.add_argument("-th", "--threshold", dest="threshold", action=CmdListAction, nargs='?', help="retrieve or set the threshold") cmdArgGroup.add_argument("-ac", "--autocalibrate", dest="auto_calib", action=CmdListAction, nargs=0, help="Send AutoCalibration command") + cmdArgGroup.add_argument("-at", "--autothreshold", dest="auto_thres", action=CmdListAction, metavar="0/1", nargs='?', help="DIS-/ENABLES Autothreshold for SniffIso15693 Codec") cmdArgGroup.add_argument("-ug", "--upgrade", dest="upgrade", action=CmdListAction, nargs=0, help="set the micro Controller to upgrade mode") args = argParser.parse_args() @@ -271,6 +283,7 @@ def main(): "rled" : cmdRedLED, "threshold" : cmdThreshold, "auto_calib": cmdAutoCalibrate, + "auto_thres": cmdAutoThreshold, "upgrade" : cmdUpgrade, } From c47974e44d5f7f6c4d3ab2672c4f20acf5f9d722 Mon Sep 17 00:00:00 2001 From: cacke-r Date: Wed, 23 Feb 2022 21:03:17 +0100 Subject: [PATCH 9/9] Sniff15693: Autocalibrate: Detect error case Detect the case, that we never receive a valid card frame. Restore original/recent threshold in this case. Signed-off-by: cacke-r --- .../Chameleon-Mini/Application/Sniff15693.c | 34 ++++++++++++++----- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/Firmware/Chameleon-Mini/Application/Sniff15693.c b/Firmware/Chameleon-Mini/Application/Sniff15693.c index cf4f87a3..db4e218a 100644 --- a/Firmware/Chameleon-Mini/Application/Sniff15693.c +++ b/Firmware/Chameleon-Mini/Application/Sniff15693.c @@ -61,10 +61,14 @@ static uint16_t max_th = 0xFFF; static uint16_t min_succ_th = 0; static uint16_t max_succ_th = 0xFFF; +/* to store the threshold which was used before we started AUTOCALIBRATION */ +static uint16_t recent_th = 0; + static bool last_cycle_successful = false; void SniffISO15693AppTimeout(void) { + CodecThresholdSet(recent_th); SniffISO15693AppReset(); } @@ -104,6 +108,10 @@ INLINE void SniffISO15693InitAutocalib(void){ min_succ_th = 0; max_succ_th = 0xFFF; + + /* store current threshold before we started AUTOCALIBRATION */ + recent_th = GlobalSettings.ActiveSettingPtr->ReaderThreshold; + last_cycle_successful = false; #ifdef ISO15693_DEBUG_LOG { @@ -119,18 +127,26 @@ INLINE void SniffISO15693InitAutocalib(void){ INLINE void SniffISO15693FinishAutocalib(void){ uint16_t new_th; - new_th = (min_succ_th + max_succ_th) >> 1; - CodecThresholdSet(new_th); + CommandStatusIdType ReturnStatusID = COMMAND_ERR_INVALID_USAGE_ID; + if(min_succ_th > 0) { + /* In this case AUTOCALIBRATION was successfull */ + new_th = (min_succ_th + max_succ_th) >> 1; + CodecThresholdSet(new_th); #ifdef ISO15693_DEBUG_LOG - { - char str[64]; - sprintf(str, "Sniff15693: Finished Autocalibration %d - %d --> % d", min_succ_th, max_succ_th, new_th); - LogEntry(LOG_INFO_GENERIC, str, strlen(str)); - } + { + char str[64]; + sprintf(str, "Sniff15693: Finished Autocalibration %d - %d --> % d", min_succ_th, max_succ_th, new_th); + LogEntry(LOG_INFO_GENERIC, str, strlen(str)); + } #endif /*#ifdef ISO15693_DEBUG_LOG*/ + ReturnStatusID = COMMAND_INFO_OK_WITH_TEXT_ID; + }else{ + /* This means we never received a valid frame - Error*/ + CodecThresholdSet(recent_th); + /* ReturnStatusID already set to error code */ + } SniffISO15693AppInit(); - CommandLinePendingTaskFinished(COMMAND_INFO_OK_WITH_TEXT_ID, NULL); - //CommandLinePendingTaskFinished(COMMAND_INFO_FALSE_ID, NULL); + CommandLinePendingTaskFinished(ReturnStatusID, NULL); } INLINE void SniffISO15693IncrementThreshold(void){