1 //-----------------------------------------------------------------------------
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
7 //-----------------------------------------------------------------------------
8 // Routines to get sample data from FPGA.
9 //-----------------------------------------------------------------------------
11 #include "proxmark3_arm.h"
13 #include "fpgaloader.h"
21 static void RAMFUNC
optimizedSniff(uint16_t *dest
, uint16_t dsize
) {
23 if (AT91C_BASE_SSC
->SSC_SR
& AT91C_SSC_RXRDY
) {
24 *dest
= (uint16_t)(AT91C_BASE_SSC
->SSC_RHR
);
26 dsize
-= sizeof(dsize
);
31 int HfSniff(uint32_t samplesToSkip
, uint32_t triggersToSkip
, uint16_t *len
) {
33 BigBuf_Clear_ext(false);
35 Dbprintf("Skipping first %d sample pairs, Skipping %d triggers", samplesToSkip
, triggersToSkip
);
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
);
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;
59 while (pressed
== false) {
62 // cancel w usb command.
63 if (interval
== 2000) {
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.
81 if (++trigger_cnt
> triggersToSkip
) {
87 pressed
= BUTTON_PRESS();
90 if (pressed
== false) {
93 while (samplesToSkip
!= 0) {
95 if (AT91C_BASE_SSC
->SSC_SR
& (AT91C_SSC_RXRDY
)) {
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);
111 FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF
);
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
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
);
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);