+ LF_Results[i] = adcval>>8; // scale int to fit in byte for graphing purposes
+ if(LF_Results[i] > peak) {
+ peakv = adcval;
+ peak = LF_Results[i];
+ peakf = i;
+ //ptr = i;
+ }
+ }
+
+ for (i=18; i >= 0; i--) LF_Results[i] = 0;
+
+ LED_A_ON();
+ // Let the FPGA drive the high-frequency antenna around 13.56 MHz.
+ FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
+ SpinDelay(20);
+ vHf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10;
+
+ cmd_send(CMD_MEASURED_ANTENNA_TUNING, vLf125 | (vLf134<<16), vHf, peakf | (peakv<<16), LF_Results, 256);
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+ LED_A_OFF();
+ LED_B_OFF();
+ return;
+}
+
+void MeasureAntennaTuningHf(void)
+{
+ int vHf = 0; // in mV
+
+ DbpString("Measuring HF antenna, press button to exit");
+
+ // Let the FPGA drive the high-frequency antenna around 13.56 MHz.
+ FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
+
+ for (;;) {
+ SpinDelay(20);
+ vHf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10;
+
+ Dbprintf("%d mV",vHf);
+ if (BUTTON_PRESS()) break;
+ }
+ DbpString("cancelled");
+
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+
+}
+
+
+void SimulateTagHfListen(void)
+{
+ // ToDo: historically this used the free buffer, which was 2744 Bytes long.
+ // There might be a better size to be defined:
+ #define HF_14B_SNOOP_BUFFER_SIZE 2744
+ uint8_t *dest = BigBuf_malloc(HF_14B_SNOOP_BUFFER_SIZE);
+ uint8_t v = 0;
+ int i;
+ int p = 0;
+
+ // We're using this mode just so that I can test it out; the simulated
+ // tag mode would work just as well and be simpler.
+ FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | FPGA_HF_READER_RX_XCORR_SNOOP);
+
+ // We need to listen to the high-frequency, peak-detected path.
+ SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+
+ FpgaSetupSsc();
+
+ i = 0;
+ for(;;) {
+ if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
+ AT91C_BASE_SSC->SSC_THR = 0xff;
+ }
+ if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
+ uint8_t r = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
+
+ v <<= 1;
+ if(r & 1) {
+ v |= 1;
+ }
+ p++;
+
+ if(p >= 8) {
+ dest[i] = v;
+ v = 0;
+ p = 0;
+ i++;
+
+ if(i >= HF_14B_SNOOP_BUFFER_SIZE) {
+ break;
+ }
+ }
+ }
+ }
+ DbpString("simulate tag (now type bitsamples)");
+}
+
+void ReadMem(int addr)
+{
+ const uint8_t *data = ((uint8_t *)addr);
+
+ Dbprintf("%x: %02x %02x %02x %02x %02x %02x %02x %02x",
+ addr, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
+}
+
+/* osimage version information is linked in */
+extern struct version_information version_information;
+/* bootrom version information is pointed to from _bootphase1_version_pointer */
+extern char *_bootphase1_version_pointer, _flash_start, _flash_end;
+void SendVersion(void)
+{
+ char temp[512]; /* Limited data payload in USB packets */
+ DbpString("Prox/RFID mark3 RFID instrument");
+
+ /* Try to find the bootrom version information. Expect to find a pointer at
+ * symbol _bootphase1_version_pointer, perform slight sanity checks on the
+ * pointer, then use it.
+ */
+ char *bootrom_version = *(char**)&_bootphase1_version_pointer;
+ if( bootrom_version < &_flash_start || bootrom_version >= &_flash_end ) {
+ DbpString("bootrom version information appears invalid");
+ } else {
+ FormatVersionInformation(temp, sizeof(temp), "bootrom: ", bootrom_version);
+ DbpString(temp);
+ }
+
+ FormatVersionInformation(temp, sizeof(temp), "os: ", &version_information);
+ DbpString(temp);
+
+ FpgaGatherVersion(temp, sizeof(temp));
+ DbpString(temp);
+ // Send Chip ID
+ cmd_send(CMD_ACK,*(AT91C_DBGU_CIDR),0,0,NULL,0);
+}
+
+#ifdef WITH_LF
+// samy's sniff and repeat routine
+void SamyRun()
+{
+ DbpString("Stand-alone mode! No PC necessary.");
+ FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
+
+ // 3 possible options? no just 2 for now
+#define OPTS 2
+
+ int high[OPTS], low[OPTS];
+
+ // Oooh pretty -- notify user we're in elite samy mode now
+ LED(LED_RED, 200);
+ LED(LED_ORANGE, 200);
+ LED(LED_GREEN, 200);
+ LED(LED_ORANGE, 200);
+ LED(LED_RED, 200);
+ LED(LED_ORANGE, 200);
+ LED(LED_GREEN, 200);
+ LED(LED_ORANGE, 200);
+ LED(LED_RED, 200);
+
+ int selected = 0;
+ int playing = 0;
+ int cardRead = 0;
+
+ // Turn on selected LED
+ LED(selected + 1, 0);
+
+ for (;;)
+ {
+ usb_poll();
+ WDT_HIT();
+
+ // Was our button held down or pressed?
+ int button_pressed = BUTTON_HELD(1000);
+ SpinDelay(300);
+
+ // Button was held for a second, begin recording
+ if (button_pressed > 0 && cardRead == 0)
+ {
+ LEDsoff();
+ LED(selected + 1, 0);
+ LED(LED_RED2, 0);
+
+ // record
+ DbpString("Starting recording");
+
+ // wait for button to be released
+ while(BUTTON_PRESS())
+ WDT_HIT();
+
+ /* need this delay to prevent catching some weird data */
+ SpinDelay(500);
+
+ CmdHIDdemodFSK(1, &high[selected], &low[selected], 0);
+ Dbprintf("Recorded %x %x %x", selected, high[selected], low[selected]);
+
+ LEDsoff();
+ LED(selected + 1, 0);
+ // Finished recording
+
+ // If we were previously playing, set playing off
+ // so next button push begins playing what we recorded
+ playing = 0;
+
+ cardRead = 1;
+
+ }
+
+ else if (button_pressed > 0 && cardRead == 1)
+ {
+ LEDsoff();
+ LED(selected + 1, 0);
+ LED(LED_ORANGE, 0);
+
+ // record
+ Dbprintf("Cloning %x %x %x", selected, high[selected], low[selected]);
+
+ // wait for button to be released
+ while(BUTTON_PRESS())
+ WDT_HIT();
+
+ /* need this delay to prevent catching some weird data */
+ SpinDelay(500);
+
+ CopyHIDtoT55x7(high[selected], low[selected], 0, 0);
+ Dbprintf("Cloned %x %x %x", selected, high[selected], low[selected]);
+
+ LEDsoff();
+ LED(selected + 1, 0);
+ // Finished recording
+
+ // If we were previously playing, set playing off
+ // so next button push begins playing what we recorded
+ playing = 0;
+
+ cardRead = 0;
+
+ }
+
+ // Change where to record (or begin playing)
+ else if (button_pressed)
+ {
+ // Next option if we were previously playing
+ if (playing)
+ selected = (selected + 1) % OPTS;
+ playing = !playing;
+
+ LEDsoff();
+ LED(selected + 1, 0);
+
+ // Begin transmitting
+ if (playing)
+ {
+ LED(LED_GREEN, 0);
+ DbpString("Playing");
+ // wait for button to be released
+ while(BUTTON_PRESS())
+ WDT_HIT();
+ Dbprintf("%x %x %x", selected, high[selected], low[selected]);
+ CmdHIDsimTAG(high[selected], low[selected], 0);
+ DbpString("Done playing");
+ if (BUTTON_HELD(1000) > 0)
+ {
+ DbpString("Exiting");
+ LEDsoff();
+ return;
+ }
+
+ /* We pressed a button so ignore it here with a delay */
+ SpinDelay(300);
+
+ // when done, we're done playing, move to next option
+ selected = (selected + 1) % OPTS;
+ playing = !playing;
+ LEDsoff();
+ LED(selected + 1, 0);
+ }
+ else
+ while(BUTTON_PRESS())
+ WDT_HIT();
+ }
+ }
+}
+#endif
+
+/*
+OBJECTIVE
+Listen and detect an external reader. Determine the best location
+for the antenna.
+
+INSTRUCTIONS:
+Inside the ListenReaderField() function, there is two mode.
+By default, when you call the function, you will enter mode 1.
+If you press the PM3 button one time, you will enter mode 2.
+If you press the PM3 button a second time, you will exit the function.
+
+DESCRIPTION OF MODE 1:
+This mode just listens for an external reader field and lights up green
+for HF and/or red for LF. This is the original mode of the detectreader
+function.
+
+DESCRIPTION OF MODE 2:
+This mode will visually represent, using the LEDs, the actual strength of the
+current compared to the maximum current detected. Basically, once you know
+what kind of external reader is present, it will help you spot the best location to place
+your antenna. You will probably not get some good results if there is a LF and a HF reader
+at the same place! :-)
+
+LIGHT SCHEME USED:
+*/
+static const char LIGHT_SCHEME[] = {
+ 0x0, /* ---- | No field detected */
+ 0x1, /* X--- | 14% of maximum current detected */
+ 0x2, /* -X-- | 29% of maximum current detected */
+ 0x4, /* --X- | 43% of maximum current detected */
+ 0x8, /* ---X | 57% of maximum current detected */
+ 0xC, /* --XX | 71% of maximum current detected */
+ 0xE, /* -XXX | 86% of maximum current detected */
+ 0xF, /* XXXX | 100% of maximum current detected */
+};
+static const int LIGHT_LEN = sizeof(LIGHT_SCHEME)/sizeof(LIGHT_SCHEME[0]);
+
+void ListenReaderField(int limit)
+{
+ int lf_av, lf_av_new, lf_baseline= 0, lf_max;
+ int hf_av, hf_av_new, hf_baseline= 0, hf_max;
+ int mode=1, display_val, display_max, i;
+
+#define LF_ONLY 1
+#define HF_ONLY 2
+#define REPORT_CHANGE 10 // report new values only if they have changed at least by REPORT_CHANGE
+
+
+ // switch off FPGA - we don't want to measure our own signal
+ FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+
+ LEDsoff();
+
+ lf_av = lf_max = AvgAdc(ADC_CHAN_LF);
+
+ if(limit != HF_ONLY) {
+ Dbprintf("LF 125/134kHz Baseline: %dmV", (MAX_ADC_LF_VOLTAGE * lf_av) >> 10);
+ lf_baseline = lf_av;
+ }
+
+ hf_av = hf_max = AvgAdc(ADC_CHAN_HF);
+
+ if (limit != LF_ONLY) {
+ Dbprintf("HF 13.56MHz Baseline: %dmV", (MAX_ADC_HF_VOLTAGE * hf_av) >> 10);
+ hf_baseline = hf_av;
+ }
+
+ for(;;) {
+ if (BUTTON_PRESS()) {
+ SpinDelay(500);
+ switch (mode) {
+ case 1:
+ mode=2;
+ DbpString("Signal Strength Mode");
+ break;
+ case 2:
+ default:
+ DbpString("Stopped");
+ LEDsoff();
+ return;
+ break;
+ }
+ }
+ WDT_HIT();
+
+ if (limit != HF_ONLY) {
+ if(mode == 1) {
+ if (abs(lf_av - lf_baseline) > REPORT_CHANGE)
+ LED_D_ON();
+ else
+ LED_D_OFF();
+ }
+
+ lf_av_new = AvgAdc(ADC_CHAN_LF);
+ // see if there's a significant change
+ if(abs(lf_av - lf_av_new) > REPORT_CHANGE) {
+ Dbprintf("LF 125/134kHz Field Change: %5dmV", (MAX_ADC_LF_VOLTAGE * lf_av_new) >> 10);
+ lf_av = lf_av_new;
+ if (lf_av > lf_max)
+ lf_max = lf_av;
+ }
+ }
+
+ if (limit != LF_ONLY) {
+ if (mode == 1){
+ if (abs(hf_av - hf_baseline) > REPORT_CHANGE)
+ LED_B_ON();
+ else
+ LED_B_OFF();
+ }
+
+ hf_av_new = AvgAdc(ADC_CHAN_HF);
+ // see if there's a significant change
+ if(abs(hf_av - hf_av_new) > REPORT_CHANGE) {
+ Dbprintf("HF 13.56MHz Field Change: %5dmV", (MAX_ADC_HF_VOLTAGE * hf_av_new) >> 10);
+ hf_av = hf_av_new;
+ if (hf_av > hf_max)
+ hf_max = hf_av;
+ }
+ }
+
+ if(mode == 2) {
+ if (limit == LF_ONLY) {
+ display_val = lf_av;
+ display_max = lf_max;
+ } else if (limit == HF_ONLY) {
+ display_val = hf_av;
+ display_max = hf_max;
+ } else { /* Pick one at random */
+ if( (hf_max - hf_baseline) > (lf_max - lf_baseline) ) {
+ display_val = hf_av;
+ display_max = hf_max;
+ } else {
+ display_val = lf_av;
+ display_max = lf_max;
+ }
+ }
+ for (i=0; i<LIGHT_LEN; i++) {
+ if (display_val >= ((display_max/LIGHT_LEN)*i) && display_val <= ((display_max/LIGHT_LEN)*(i+1))) {
+ if (LIGHT_SCHEME[i] & 0x1) LED_C_ON(); else LED_C_OFF();
+ if (LIGHT_SCHEME[i] & 0x2) LED_A_ON(); else LED_A_OFF();
+ if (LIGHT_SCHEME[i] & 0x4) LED_B_ON(); else LED_B_OFF();
+ if (LIGHT_SCHEME[i] & 0x8) LED_D_ON(); else LED_D_OFF();
+ break;
+ }
+ }
+ }
+ }
+}