Merge pull request #1331 from Guilhem7/master
[RRG-proxmark3.git] / armsrc / hfsnoop.c
blob4e4539f3e1dc21fe9a396ffe84b7fa3ba653ae0d
1 //-----------------------------------------------------------------------------
2 // piwi, 2019
3 //
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
6 // the license.
7 //-----------------------------------------------------------------------------
8 // Routines to get sample data from FPGA.
9 //-----------------------------------------------------------------------------
10 #include "hfsnoop.h"
11 #include "proxmark3_arm.h"
12 #include "BigBuf.h"
13 #include "fpgaloader.h"
14 #include "ticks.h"
15 #include "dbprint.h"
16 #include "util.h"
17 #include "fpga.h"
18 #include "appmain.h"
19 #include "cmd.h"
21 static void RAMFUNC optimizedSniff(uint16_t *dest, uint16_t dsize) {
22 while (dsize > 0) {
23 if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
24 *dest = (uint16_t)(AT91C_BASE_SSC->SSC_RHR);
25 dest++;
26 dsize -= sizeof(dsize);
31 int HfSniff(uint32_t samplesToSkip, uint32_t triggersToSkip, uint16_t *len) {
32 BigBuf_free();
33 BigBuf_Clear_ext(false);
35 Dbprintf("Skipping first %d sample pairs, Skipping %d triggers", samplesToSkip, triggersToSkip);
37 LED_D_ON();
39 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
41 SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
43 // Set up the synchronous serial port
44 FpgaSetupSsc(FPGA_MAJOR_MODE_HF_SNIFF);
46 // Setting Frame Mode For better performance on high speed data transfer.
47 AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(16);
49 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SNIFF);
50 SpinDelay(100);
52 *len = (BigBuf_max_traceLen() & 0xFFFE);
53 uint8_t *mem = BigBuf_malloc(*len);
55 uint32_t trigger_cnt = 0;
56 uint16_t r = 0, interval = 0;
58 bool pressed = false;
59 while (pressed == false) {
60 WDT_HIT();
62 // cancel w usb command.
63 if (interval == 2000) {
64 if (data_available())
65 break;
67 interval = 0;
68 } else {
69 interval++;
72 // check if trigger is reached
73 if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
74 r = (uint16_t)AT91C_BASE_SSC->SSC_RHR;
76 r = MAX(r & 0xFF, r >> 8);
78 // 180 (0xB4) arbitary value to see if a strong RF field is near.
79 if (r > 180) {
81 if (++trigger_cnt > triggersToSkip) {
82 break;
87 pressed = BUTTON_PRESS();
90 if (pressed == false) {
92 // skip samples loop
93 while (samplesToSkip != 0) {
95 if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
96 samplesToSkip--;
100 optimizedSniff((uint16_t *)mem, *len);
102 if (DBGLEVEL >= DBG_INFO) {
103 Dbprintf("Trigger kicked in (%d >= 180)", r);
104 Dbprintf("Collected %u samples", *len);
108 //Resetting Frame mode (First set in fpgaloader.c)
109 AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
110 LED_D_OFF();
111 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
112 BigBuf_free();
113 return (pressed) ? PM3_EOPABORTED : PM3_SUCCESS;
116 void HfPlotDownload(void) {
118 tosend_t *ts = get_tosend();
119 uint8_t *this_buf = ts->buf;
121 FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
123 FpgaSetupSsc(FPGA_MAJOR_MODE_HF_GET_TRACE);
125 AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; // Disable DMA Transfer
126 AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) this_buf; // start transfer to this memory address
127 AT91C_BASE_PDC_SSC->PDC_RCR = PM3_CMD_DATA_SIZE; // transfer this many samples
128 ts->buf[0] = (uint8_t)AT91C_BASE_SSC->SSC_RHR; // clear receive register
129 AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN; // Start DMA transfer
131 FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_GET_TRACE); // let FPGA transfer its internal Block-RAM
133 LED_B_ON();
134 for (size_t i = 0; i < FPGA_TRACE_SIZE; i += PM3_CMD_DATA_SIZE) {
135 // prepare next DMA transfer:
136 uint8_t *next_buf = ts->buf + ((i + PM3_CMD_DATA_SIZE) % (2 * PM3_CMD_DATA_SIZE));
138 AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t)next_buf;
139 AT91C_BASE_PDC_SSC->PDC_RNCR = PM3_CMD_DATA_SIZE;
141 size_t len = MIN(FPGA_TRACE_SIZE - i, PM3_CMD_DATA_SIZE);
143 while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_ENDRX))) {}; // wait for DMA transfer to complete
145 reply_old(CMD_FPGAMEM_DOWNLOADED, i, len, FPGA_TRACE_SIZE, this_buf, len);
146 this_buf = next_buf;
149 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
151 // Trigger a finish downloading signal with an ACK frame
152 reply_mix(CMD_ACK, 1, 0, FPGA_TRACE_SIZE, 0, 0);
153 LED_B_OFF();