// LEGIC RF simulation code
//-----------------------------------------------------------------------------
+#include "legicrf.h"
+
#include "proxmark3.h"
#include "apps.h"
#include "util.h"
#include "string.h"
-
-#include "legicrf.h"
#include "legic_prng.h"
#include "legic.h"
#include "crc.h"
+#include "fpgaloader.h"
static legic_card_select_t card;/* metadata of currently selected card */
static crc_t legic_crc;
// I/O interface abstraction (FPGA -> ARM)
//-----------------------------------------------------------------------------
-static inline uint8_t rx_byte_from_fpga() {
+static inline uint16_t rx_frame_from_fpga() {
for(;;) {
WDT_HIT();
- // wait for byte be become available in rx holding register
+ // wait for frame be become available in rx holding register
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
return AT91C_BASE_SSC->SSC_RHR;
}
// To reduce CPU time the amplitude is approximated by using linear functions:
// am = MAX(ABS(i),ABS(q)) + 1/2*MIN(ABS(i),ABSq))
//
-// Note: The SSC receiver is never synchronized the calculation my be performed
-// on a I/Q pair from two subsequent correlations, but does not matter.
-//
// The bit time is 99.1us (21 I/Q pairs). The receiver skips the first 5 samples
// and averages the next (most stable) 8 samples. The final 8 samples are dropped
// also.
//
-// The demedulated should be alligned to the bit periode by the caller. This is
+// The demodulated should be alligned to the bit period by the caller. This is
// done in rx_bit and rx_ack.
static inline bool rx_bit() {
- int32_t cq = 0;
- int32_t ci = 0;
+ int32_t sum_cq = 0;
+ int32_t sum_ci = 0;
// skip first 5 I/Q pairs
for(size_t i = 0; i<5; ++i) {
- (int8_t)rx_byte_from_fpga();
- (int8_t)rx_byte_from_fpga();
+ (void)rx_frame_from_fpga();
}
// sample next 8 I/Q pairs
for(size_t i = 0; i<8; ++i) {
- cq += (int8_t)rx_byte_from_fpga();
- ci += (int8_t)rx_byte_from_fpga();
+ uint16_t iq = rx_frame_from_fpga();
+ int8_t ci = (int8_t)(iq >> 8);
+ int8_t cq = (int8_t)(iq & 0xff);
+ sum_ci += ci;
+ sum_cq += cq;
}
// calculate power
- int32_t power = (MAX(ABS(ci), ABS(cq)) + (MIN(ABS(ci), ABS(cq)) >> 1));
+ int32_t power = (MAX(ABS(sum_ci), ABS(sum_cq)) + MIN(ABS(sum_ci), ABS(sum_cq))/2);
// compare average (power / 8) to threshold
return ((power >> 3) > INPUT_THRESHOLD);
static inline void tx_bit(bool bit) {
// insert pause
- LOW(GPIO_SSC_DOUT);
+ HIGH(GPIO_SSC_DOUT);
last_frame_end += RWD_TIME_PAUSE;
while(GET_TICKS < last_frame_end) { };
- HIGH(GPIO_SSC_DOUT);
- // return to high, wait for bit periode to end
+ // return to carrier on, wait for bit periode to end
+ LOW(GPIO_SSC_DOUT);
last_frame_end += (bit ? RWD_TIME_1 : RWD_TIME_0) - RWD_TIME_PAUSE;
while(GET_TICKS < last_frame_end) { };
}
//-----------------------------------------------------------------------------
static void tx_frame(uint32_t frame, uint8_t len) {
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX);
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_MODE_SEND_FULL_MOD);
// wait for next tx timeslot
last_frame_end += RWD_FRAME_WAIT;
};
// add pause to mark end of the frame
- LOW(GPIO_SSC_DOUT);
+ HIGH(GPIO_SSC_DOUT);
last_frame_end += RWD_TIME_PAUSE;
while(GET_TICKS < last_frame_end) { };
- HIGH(GPIO_SSC_DOUT);
+ LOW(GPIO_SSC_DOUT);
}
static uint32_t rx_frame(uint8_t len) {
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR
- | FPGA_HF_READER_RX_XCORR_848_KHZ
- | FPGA_HF_READER_RX_XCORR_QUARTER_FREQ);
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_SUBCARRIER_212_KHZ | FPGA_HF_READER_MODE_RECEIVE_IQ);
// hold sampling until card is expected to respond
last_frame_end += TAG_FRAME_WAIT;
static bool rx_ack() {
// change fpga into rx mode
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR
- | FPGA_HF_READER_RX_XCORR_848_KHZ
- | FPGA_HF_READER_RX_XCORR_QUARTER_FREQ);
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_SUBCARRIER_212_KHZ | FPGA_HF_READER_MODE_RECEIVE_IQ);
// hold sampling until card is expected to respond
last_frame_end += TAG_FRAME_WAIT;
static void init_reader(bool clear_mem) {
// configure FPGA
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
- FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR
- | FPGA_HF_READER_RX_XCORR_848_KHZ
- | FPGA_HF_READER_RX_XCORR_QUARTER_FREQ);
+ FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_SUBCARRIER_212_KHZ | FPGA_HF_READER_MODE_RECEIVE_IQ);
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
LED_D_ON();
// configure SSC with defaults
- FpgaSetupSsc();
+ FpgaSetupSsc(FPGA_MAJOR_MODE_HF_READER);
// re-claim GPIO_SSC_DOUT as GPIO and enable output
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
- HIGH(GPIO_SSC_DOUT);
+ LOW(GPIO_SSC_DOUT);
// init crc calculator
crc_init(&legic_crc, 4, 0x19 >> 1, 0x05, 0);
// establish shared secret and detect card type
DbpString("Reading card ...");
uint8_t card_type = setup_phase(SESSION_IV);
+ uint8_t result = 0;
if(init_card(card_type, &card) != 0) {
- Dbprintf("No or unknown card found, aborting");
+ result = 1;
goto OUT;
}
for(uint16_t i = 0; i < bytes; ++i) {
int16_t byte = read_byte(offset + i, card.cmdsize);
if(byte == -1) {
- Dbprintf("operation failed @ 0x%03.3x", bytes);
+ result = 2;
goto OUT;
}
BigBuf[i] = byte;
}
- // OK
- Dbprintf("Card (MIM %i) read, use 'hf legic decode' or", card.cardsize);
- Dbprintf("'data hexsamples %d' to view results", (bytes+7) & ~7);
-
OUT:
+ cmd_send(CMD_ACK, result, bytes, 0, &card, sizeof(card));
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_B_OFF();
LED_C_OFF();