mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 13:53:55 -07:00
aa
This commit is contained in:
parent
438cada2cf
commit
9b3bc55136
3 changed files with 178 additions and 55 deletions
138
armsrc/em4x50.c
138
armsrc/em4x50.c
|
@ -62,6 +62,26 @@ static void wait_timer(uint32_t period) {
|
||||||
while (AT91C_BASE_TC0->TC_CV < period);
|
while (AT91C_BASE_TC0->TC_CV < period);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void catch_samples(void) {
|
||||||
|
|
||||||
|
uint8_t sample = 0;
|
||||||
|
|
||||||
|
if (EM4X50_MAX_NO_SAMPLES > CARD_MEMORY_SIZE) {
|
||||||
|
Dbprintf("exeeded emulator memory size");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t *em4x50_sample_buffer = BigBuf_get_addr();
|
||||||
|
|
||||||
|
memcpy(em4x50_sample_buffer, &gHigh, 1);
|
||||||
|
memcpy(em4x50_sample_buffer + 1, &gLow, 1);
|
||||||
|
|
||||||
|
for (int i = 2; i < EM4X50_MAX_NO_SAMPLES + 2; i++) {
|
||||||
|
sample = AT91C_BASE_SSC->SSC_RHR;
|
||||||
|
memcpy(em4x50_sample_buffer + i, &sample, 1);
|
||||||
|
wait_timer(T0); // 8µs delay
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// extract and check parities
|
// extract and check parities
|
||||||
// return result of parity check and extracted plain data
|
// return result of parity check and extracted plain data
|
||||||
|
@ -242,11 +262,13 @@ static bool invalid_bit(void) {
|
||||||
|
|
||||||
// get sample at 3/4 of bit period
|
// get sample at 3/4 of bit period
|
||||||
wait_timer(T0 * EM4X50_T_TAG_THREE_QUARTER_PERIOD);
|
wait_timer(T0 * EM4X50_T_TAG_THREE_QUARTER_PERIOD);
|
||||||
|
//wait_timer(T0 * EM4X50_T_TAG_HALF_PERIOD);
|
||||||
|
|
||||||
uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||||
|
|
||||||
// wait until end of bit period
|
// wait until end of bit period
|
||||||
wait_timer(T0 * EM4X50_T_TAG_QUARTER_PERIOD);
|
wait_timer(T0 * EM4X50_T_TAG_QUARTER_PERIOD);
|
||||||
|
//wait_timer(T0 * EM4X50_T_TAG_HALF_PERIOD);
|
||||||
|
|
||||||
// bit in "undefined" state?
|
// bit in "undefined" state?
|
||||||
if (sample <= gHigh && sample >= gLow)
|
if (sample <= gHigh && sample >= gLow)
|
||||||
|
@ -422,6 +444,8 @@ static int find_double_listen_window(bool bcommand) {
|
||||||
|
|
||||||
// skip the next bit...
|
// skip the next bit...
|
||||||
wait_timer(T0 * EM4X50_T_TAG_FULL_PERIOD);
|
wait_timer(T0 * EM4X50_T_TAG_FULL_PERIOD);
|
||||||
|
catch_samples();
|
||||||
|
break;
|
||||||
|
|
||||||
// ...and check if the following bit does make sense
|
// ...and check if the following bit does make sense
|
||||||
// (if not it is the correct position within the second
|
// (if not it is the correct position within the second
|
||||||
|
@ -723,24 +747,11 @@ static bool em4x50_sim_send_word(uint32_t word) {
|
||||||
|
|
||||||
static bool em4x50_sim_send_listen_window(void) {
|
static bool em4x50_sim_send_listen_window(void) {
|
||||||
|
|
||||||
bool cond = false;
|
|
||||||
uint16_t check = 0;
|
uint16_t check = 0;
|
||||||
uint32_t tval1[5 * EM4X50_T_TAG_FULL_PERIOD] = {0};
|
|
||||||
uint32_t tval2[5 * EM4X50_T_TAG_FULL_PERIOD] = {0};
|
|
||||||
|
|
||||||
StartTicks();
|
|
||||||
|
|
||||||
for (int t = 0; t < 5 * EM4X50_T_TAG_FULL_PERIOD; t++) {
|
for (int t = 0; t < 5 * EM4X50_T_TAG_FULL_PERIOD; t++) {
|
||||||
|
|
||||||
cond = ((t >= 3 * EM4X50_T_TAG_FULL_PERIOD) && (t < 4 * EM4X50_T_TAG_FULL_PERIOD));
|
|
||||||
|
|
||||||
// wait until SSC_CLK goes HIGH
|
// wait until SSC_CLK goes HIGH
|
||||||
if (cond) {
|
|
||||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG;
|
|
||||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
|
|
||||||
while (AT91C_BASE_TC0->TC_CV > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)) {
|
while (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
|
|
||||||
|
@ -751,8 +762,6 @@ static bool em4x50_sim_send_listen_window(void) {
|
||||||
}
|
}
|
||||||
++check;
|
++check;
|
||||||
}
|
}
|
||||||
if (cond)
|
|
||||||
tval1[t] = GetTicks();
|
|
||||||
|
|
||||||
if (t >= 4 * EM4X50_T_TAG_FULL_PERIOD)
|
if (t >= 4 * EM4X50_T_TAG_FULL_PERIOD)
|
||||||
SHORT_COIL();
|
SHORT_COIL();
|
||||||
|
@ -768,12 +777,6 @@ static bool em4x50_sim_send_listen_window(void) {
|
||||||
check = 0;
|
check = 0;
|
||||||
|
|
||||||
// wait until SSC_CLK goes LOW
|
// wait until SSC_CLK goes LOW
|
||||||
if (cond) {
|
|
||||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG;
|
|
||||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
|
|
||||||
while (AT91C_BASE_TC0->TC_CV > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) {
|
while (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
if (check == 1000) {
|
if (check == 1000) {
|
||||||
|
@ -783,16 +786,8 @@ static bool em4x50_sim_send_listen_window(void) {
|
||||||
}
|
}
|
||||||
++check;
|
++check;
|
||||||
}
|
}
|
||||||
if (cond)
|
|
||||||
tval2[t] = GetTicks();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int t = 0; t < 5 * EM4X50_T_TAG_FULL_PERIOD; t++) {
|
|
||||||
//if (tval[t] > 4)
|
|
||||||
Dbprintf("%3i probably RM intialization found: delta = %i %i", t, tval1[t], tval2[t]);
|
|
||||||
}
|
|
||||||
Dbprintf("");
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1315,33 +1310,72 @@ void em4x50_test(em4x50_test_t *ett) {
|
||||||
|
|
||||||
int status = PM3_EFAILED;
|
int status = PM3_EFAILED;
|
||||||
|
|
||||||
em4x50_setup_read();
|
// set field on or off
|
||||||
|
if (ett->field != -1) {
|
||||||
if (ett->field) {
|
em4x50_setup_read();
|
||||||
LOW(GPIO_SSC_DOUT);
|
if (ett->field == 1) {
|
||||||
LED_A_ON();
|
LED_A_ON();
|
||||||
|
} else {
|
||||||
if (DBGLEVEL >= DBG_DEBUG)
|
HIGH(GPIO_SSC_DOUT);
|
||||||
Dbprintf("switched field on");
|
LED_A_OFF();
|
||||||
|
}
|
||||||
status = 1;
|
status = ett->field;
|
||||||
} else {
|
|
||||||
HIGH(GPIO_SSC_DOUT);
|
|
||||||
LED_A_OFF();
|
|
||||||
|
|
||||||
if (DBGLEVEL >= DBG_DEBUG)
|
|
||||||
Dbprintf("switched field off");
|
|
||||||
|
|
||||||
status = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
while (BUTTON_PRESS() == false) {
|
// check field status
|
||||||
|
if (ett->check_field) {
|
||||||
|
em4x50_setup_sim();
|
||||||
|
bool field_on = false;
|
||||||
|
while (BUTTON_PRESS() == false) {
|
||||||
|
|
||||||
if (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) {
|
if (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)) {
|
||||||
Dbprintf("field on");
|
if (field_on == false) {
|
||||||
} else if (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)){
|
Dbprintf("field on");
|
||||||
Dbprintf("field on");
|
field_on = true;
|
||||||
|
}
|
||||||
|
} else if (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK){
|
||||||
|
if (field_on == true) {
|
||||||
|
Dbprintf("field off");
|
||||||
|
field_on = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
status = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// timing values
|
||||||
|
if (ett->cycles != 0) {
|
||||||
|
uint32_t tval = 0;
|
||||||
|
uint32_t tvalhigh[ett->cycles];
|
||||||
|
uint32_t tvallow[ett->cycles];
|
||||||
|
|
||||||
|
em4x50_setup_sim();
|
||||||
|
AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0);
|
||||||
|
AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
|
||||||
|
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
|
||||||
|
AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK;
|
||||||
|
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
|
||||||
|
while (AT91C_BASE_TC0->TC_CV > 0);
|
||||||
|
|
||||||
|
for (int t = 0; t < ett->cycles; t++) {
|
||||||
|
|
||||||
|
// field on -> high value
|
||||||
|
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
|
||||||
|
tval = AT91C_BASE_TC0->TC_CV;
|
||||||
|
while (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK));
|
||||||
|
tvalhigh[t] = AT91C_BASE_TC0->TC_CV - tval;
|
||||||
|
|
||||||
|
// filed off -> zero value
|
||||||
|
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
|
||||||
|
tval = AT91C_BASE_TC0->TC_CV;
|
||||||
|
while (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK);
|
||||||
|
tvallow[t] = AT91C_BASE_TC0->TC_CV - tval;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int t = 0; t < ett->cycles; t++) {
|
||||||
|
Dbprintf("%03i %li %li", t, tvallow[t], tvalhigh[t]);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
reply_ng(CMD_LF_EM4X50_TEST, status, NULL, 0);
|
reply_ng(CMD_LF_EM4X50_TEST, status, NULL, 0);
|
||||||
|
|
|
@ -23,6 +23,61 @@
|
||||||
|
|
||||||
static int CmdHelp(const char *Cmd);
|
static int CmdHelp(const char *Cmd);
|
||||||
|
|
||||||
|
static void write_gnuplot_config_file(int gHigh, int gLow) {
|
||||||
|
|
||||||
|
const char *fn = "../data/data.gnu";
|
||||||
|
FILE *fp = NULL;
|
||||||
|
|
||||||
|
if ((fp = fopen(fn, "w+")) == false) {
|
||||||
|
PrintAndLogEx(WARNING, "Fail, open file %s", fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(fp, "set term qt size 1400, 350 enhanced\n");
|
||||||
|
fprintf(fp, "set border 31 front linecolor rgb 'dark-grey' linewidth 1.000 dashtype solid\n");
|
||||||
|
fprintf(fp, "set xtics 0, 1 textcolor rgb 'dark-grey'\n");
|
||||||
|
fprintf(fp, "set ytics 0, 64 textcolor rgb 'dark-grey'\n");
|
||||||
|
fprintf(fp, "set title 'EM4x50 signal (amplitude vs time)'\n");
|
||||||
|
fprintf(fp, "set title font ',14' textcolor rgb 'white'\n");
|
||||||
|
fprintf(fp, "set xlabel 'time / ms'\n");
|
||||||
|
fprintf(fp, "set xlabel font ',12' textcolor rgb 'dark-grey'\n");
|
||||||
|
fprintf(fp, "set ylabel 'amplitude'\n");
|
||||||
|
fprintf(fp, "set ylabel font ',12' textcolor rgb 'dark-grey'\n");
|
||||||
|
fprintf(fp, "set key textcolor 'green'\n");
|
||||||
|
fprintf(fp, "set grid\n");
|
||||||
|
fprintf(fp, "#set time textcolor 'dark-grey'\n");
|
||||||
|
fprintf(fp, "plot [0:][-50:300] '../data/data.dat' u ($1/1000):2 w l linecolor 'green' title '500/4', '../data/data.dat' u ($1/1000):3 w l linecolor 'yellow' title 'gHigh = %i', '../data/data.dat' u ($1/1000):4 w l linecolor 'yellow' title 'gLow = %i'\n", gHigh, gLow);
|
||||||
|
fprintf(fp, "pause -1\n");
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void get_samples(void) {
|
||||||
|
|
||||||
|
int gHigh = 0, gLow = 0;
|
||||||
|
const char *fn = "../data/data.dat";
|
||||||
|
FILE *fp = NULL;
|
||||||
|
|
||||||
|
// download from BigBuf memory
|
||||||
|
uint8_t data[EM4X50_MAX_NO_SAMPLES + 2] = {0x0};
|
||||||
|
if (GetFromDevice(BIG_BUF, data, EM4X50_MAX_NO_SAMPLES + 2, 0, NULL, 0, NULL, 2500, false) == false) {
|
||||||
|
PrintAndLogEx(WARNING, "Fail, transfer from device time-out");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((fp = fopen(fn, "w+")) == false) {
|
||||||
|
PrintAndLogEx(WARNING, "Fail, open file %s", fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
gHigh = data[0];
|
||||||
|
gLow = data[1];
|
||||||
|
for (int i = 2; i < EM4X50_MAX_NO_SAMPLES + 2; i++) {
|
||||||
|
fprintf(fp, "%i %i %i %i\n", (i - 2) * 8, data[i], gHigh, gLow);
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(fp);
|
||||||
|
|
||||||
|
write_gnuplot_config_file(gHigh, gLow);
|
||||||
|
}
|
||||||
|
|
||||||
static void prepare_result(const uint8_t *data, int fwr, int lwr, em4x50_word_t *words) {
|
static void prepare_result(const uint8_t *data, int fwr, int lwr, em4x50_word_t *words) {
|
||||||
|
|
||||||
// restructure received result in "em4x50_word_t" structure
|
// restructure received result in "em4x50_word_t" structure
|
||||||
|
@ -612,6 +667,8 @@ int CmdEM4x50Read(const char *Cmd) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get_samples();
|
||||||
|
|
||||||
return em4x50_read(&etd, NULL);
|
return em4x50_read(&etd, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1162,19 +1219,43 @@ int CmdEM4x50Test(const char *Cmd) {
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "lf em 4x50 test",
|
CLIParserInit(&ctx, "lf em 4x50 test",
|
||||||
"perform EM4x50 tests.",
|
"perform EM4x50 tests.",
|
||||||
"lf em 4x50 test --field 1 -> reader field on \n"
|
"lf em 4x50 test --field on -> reader field on\n"
|
||||||
|
"lf em 4x50 test --field off -> reader field off\n"
|
||||||
|
"lf em 4x50 test --check -> check on/off status of reader field\n"
|
||||||
|
"lf em 4x50 test --cycles 100 -> measure time of 100 field cycles\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
void *argtable[] = {
|
void *argtable[] = {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
arg_lit0("", "field", "field off/on"),
|
arg_str0(NULL, "field", "on/off", "field on/off"),
|
||||||
|
arg_lit0(NULL, "check", "check if field is on or off"),
|
||||||
|
arg_int0(NULL, "cycles", "<dec>", "number of field cycles"),
|
||||||
arg_param_end
|
arg_param_end
|
||||||
};
|
};
|
||||||
|
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
|
|
||||||
em4x50_test_t ett;
|
// option: field
|
||||||
ett.field = arg_get_lit(ctx, 1);
|
int slen = 0;
|
||||||
|
char format[3] = {0};
|
||||||
|
CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)format, sizeof(format), &slen);
|
||||||
|
em4x50_test_t ett = {.field = -1};
|
||||||
|
if (slen != 0) {
|
||||||
|
if (strcmp(format, "on") == 0) {
|
||||||
|
ett.field = 1;
|
||||||
|
} else if (strcmp(format, "off") == 0) {
|
||||||
|
ett.field = 0;
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(INFO, "Unknown option for --field: %s", format);
|
||||||
|
return PM3_ESOFT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// option: check_field
|
||||||
|
ett.check_field = arg_get_lit(ctx, 2);
|
||||||
|
// option: cycles
|
||||||
|
ett.cycles = arg_get_int_def(ctx, 3, 0);
|
||||||
|
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
// start
|
// start
|
||||||
|
@ -1185,9 +1266,14 @@ int CmdEM4x50Test(const char *Cmd) {
|
||||||
|
|
||||||
// print response
|
// print response
|
||||||
if (resp.status == 1) {
|
if (resp.status == 1) {
|
||||||
PrintAndLogEx(SUCCESS, "Field switched " _GREEN_("on"));
|
if (ett.field == 1)
|
||||||
|
PrintAndLogEx(SUCCESS, "Field switched " _GREEN_("on"));
|
||||||
|
if (ett.check_field == 1)
|
||||||
|
PrintAndLogEx(SUCCESS, "Field status evaluated");
|
||||||
} else if (resp.status == 0) {
|
} else if (resp.status == 0) {
|
||||||
PrintAndLogEx(SUCCESS, "Field switched " _GREEN_("off"));
|
PrintAndLogEx(SUCCESS, "Field switched " _GREEN_("off"));
|
||||||
|
} else if (resp.status == -1) {
|
||||||
|
PrintAndLogEx(INFO, "Nothing done");
|
||||||
} else {
|
} else {
|
||||||
PrintAndLogEx(FAILED, "Test call " _RED_("failed"));
|
PrintAndLogEx(FAILED, "Test call " _RED_("failed"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
// misc
|
// misc
|
||||||
#define TIMEOUT 2000
|
#define TIMEOUT 2000
|
||||||
#define DUMP_FILESIZE 136
|
#define DUMP_FILESIZE 136
|
||||||
|
#define EM4X50_MAX_NO_SAMPLES 1000
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool addr_given;
|
bool addr_given;
|
||||||
|
@ -47,7 +48,9 @@ typedef struct {
|
||||||
} PACKED em4x50_data_t;
|
} PACKED em4x50_data_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
bool field;
|
bool check_field;
|
||||||
|
int field;
|
||||||
|
int cycles;
|
||||||
} PACKED em4x50_test_t;
|
} PACKED em4x50_test_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue