undo NfcA changes which might have looked better, but brought no reliability improvement

This commit is contained in:
g3gg0
2022-11-25 12:08:36 +01:00
parent c1b5394b0f
commit 0cb784aadd
7 changed files with 49 additions and 253 deletions

View File

@@ -368,7 +368,6 @@ void furi_hal_nfc_listen_start(FuriHalNfcDevData* nfc_data) {
} }
void furi_hal_nfcv_listen_start() { void furi_hal_nfcv_listen_start() {
furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeInput, GpioPullDown, GpioSpeedVeryHigh); furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeInput, GpioPullDown, GpioSpeedVeryHigh);
// Clear interrupts // Clear interrupts
st25r3916ClearInterrupts(); st25r3916ClearInterrupts();
@@ -536,8 +535,9 @@ static bool furi_hal_nfc_transparent_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_
// Send signal // Send signal
FURI_CRITICAL_ENTER(); FURI_CRITICAL_ENTER();
nfca_signal_encode(tx_rx->nfca_signal, tx_rx->tx_data, tx_rx->tx_bits, tx_rx->tx_parity); nfca_signal_encode(tx_rx->nfca_signal, tx_rx->tx_data, tx_rx->tx_bits, tx_rx->tx_parity);
digital_sequence_send(tx_rx->nfca_signal->tx_signal); digital_signal_send(tx_rx->nfca_signal->tx_signal, &gpio_spi_r_mosi);
FURI_CRITICAL_EXIT(); FURI_CRITICAL_EXIT();
furi_hal_gpio_write(&gpio_spi_r_mosi, false);
// Configure gpio back to SPI and exit transparent // Configure gpio back to SPI and exit transparent
furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc); furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc);
@@ -601,51 +601,6 @@ static bool furi_hal_nfc_transparent_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_
return ret; return ret;
} }
static bool furi_hal_nfc_fully_transparent_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) {
furi_assert(tx_rx);
bool received = false;
tx_rx->rx_bits = 0;
if(tx_rx->tx_bits) {
nfca_trans_rx_pause(&tx_rx->nfca_trans_state);
FURI_CRITICAL_ENTER();
furi_hal_gpio_write(&gpio_spi_r_mosi, false);
nfca_signal_encode(tx_rx->nfca_signal, tx_rx->tx_data, tx_rx->tx_bits, tx_rx->tx_parity);
digital_sequence_send(tx_rx->nfca_signal->tx_signal);
furi_hal_gpio_write(&gpio_spi_r_mosi, false);
FURI_CRITICAL_EXIT();
nfca_trans_rx_continue(&tx_rx->nfca_trans_state);
if(tx_rx->sniff_tx) {
tx_rx->sniff_tx(tx_rx->tx_data, tx_rx->tx_bits, false, tx_rx->sniff_context);
}
}
if(timeout_ms) {
tx_rx->nfca_trans_state.bits_received = 0;
received = nfca_trans_rx_loop(&tx_rx->nfca_trans_state, timeout_ms);
if(received) {
if(tx_rx->nfca_trans_state.bits_received > 7) {
tx_rx->rx_bits = tx_rx->nfca_trans_state.bits_received/9 * 8;
memcpy(tx_rx->rx_data, tx_rx->nfca_trans_state.frame_data, tx_rx->nfca_trans_state.bits_received/9);
} else {
tx_rx->rx_bits = tx_rx->nfca_trans_state.bits_received;
tx_rx->rx_data[0] = tx_rx->nfca_trans_state.frame_data[0] & ~(0xFF << tx_rx->rx_bits);
}
if(tx_rx->sniff_rx) {
tx_rx->sniff_rx(tx_rx->rx_data, tx_rx->rx_bits, false, tx_rx->sniff_context);
}
}
}
return received;
}
static uint32_t furi_hal_nfc_tx_rx_get_flag(FuriHalNfcTxRxType type) { static uint32_t furi_hal_nfc_tx_rx_get_flag(FuriHalNfcTxRxType type) {
uint32_t flags = 0; uint32_t flags = 0;
@@ -719,26 +674,6 @@ uint16_t furi_hal_nfc_bitstream_to_data_and_parity(
return curr_byte * 8; return curr_byte * 8;
} }
static uint8_t furi_hal_nfc_gen_parity(uint8_t value) {
value ^= (value >> 4);
value ^= (value >> 2);
value ^= (value >> 1);
return (value ^ 1) & 1;
}
void furi_hal_nfc_gen_bitstream(FuriHalNfcTxRxContext* tx_rx, uint8_t *buffer, size_t len) {
for(size_t pos = 0; pos < len; pos++) {
uint32_t parity_bit_num = pos % 8;
uint8_t bit = furi_hal_nfc_gen_parity(buffer[pos]);
tx_rx->tx_data[pos] = buffer[pos];
tx_rx->tx_parity[pos / 8] &= ~(1 << (7 - parity_bit_num));
tx_rx->tx_parity[pos / 8] |= bit << (7 - parity_bit_num);
}
tx_rx->tx_bits = len * 8;
}
bool furi_hal_nfc_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) { bool furi_hal_nfc_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) {
furi_assert(tx_rx); furi_assert(tx_rx);
@@ -749,11 +684,6 @@ bool furi_hal_nfc_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_t timeout_ms) {
uint8_t* temp_rx_buff = NULL; uint8_t* temp_rx_buff = NULL;
uint16_t* temp_rx_bits = NULL; uint16_t* temp_rx_bits = NULL;
/* send and receive data using transparent mode */
if(tx_rx->tx_rx_type == FuriHalNfcTxRxFullyTransparent) {
return furi_hal_nfc_fully_transparent_tx_rx(tx_rx, timeout_ms);
}
/* send data using transparent mode and receive data in standard mode */
if(tx_rx->tx_rx_type == FuriHalNfcTxRxTransparent) { if(tx_rx->tx_rx_type == FuriHalNfcTxRxTransparent) {
return furi_hal_nfc_transparent_tx_rx(tx_rx, timeout_ms); return furi_hal_nfc_transparent_tx_rx(tx_rx, timeout_ms);
} }

View File

@@ -14,7 +14,6 @@ extern "C" {
#endif #endif
#include <rfal_nfc.h> #include <rfal_nfc.h>
#include <lib/nfc/protocols/nfca.h> #include <lib/nfc/protocols/nfca.h>
#include <lib/nfc/protocols/nfca_trans_rx.h>
#define FURI_HAL_NFC_UID_MAX_LEN 10 #define FURI_HAL_NFC_UID_MAX_LEN 10
#define FURI_HAL_NFC_DATA_BUFF_SIZE (512) #define FURI_HAL_NFC_DATA_BUFF_SIZE (512)
@@ -47,7 +46,6 @@ typedef enum {
FuriHalNfcTxRxTypeRaw, FuriHalNfcTxRxTypeRaw,
FuriHalNfcTxRxTypeRxRaw, FuriHalNfcTxRxTypeRxRaw,
FuriHalNfcTxRxTransparent, FuriHalNfcTxRxTransparent,
FuriHalNfcTxRxFullyTransparent
} FuriHalNfcTxRxType; } FuriHalNfcTxRxType;
typedef bool (*FuriHalNfcEmulateCallback)( typedef bool (*FuriHalNfcEmulateCallback)(
@@ -93,8 +91,6 @@ typedef struct {
uint16_t rx_bits; uint16_t rx_bits;
FuriHalNfcTxRxType tx_rx_type; FuriHalNfcTxRxType tx_rx_type;
NfcaSignal* nfca_signal; NfcaSignal* nfca_signal;
NfcaTransRxState nfca_trans_state;
bool nfca_trans_initialized;
FuriHalNfcTxRxSniffCallback sniff_tx; FuriHalNfcTxRxSniffCallback sniff_tx;
FuriHalNfcTxRxSniffCallback sniff_rx; FuriHalNfcTxRxSniffCallback sniff_rx;
@@ -429,9 +425,6 @@ FuriHalNfcReturn furi_hal_nfc_ll_txrx_bits(
void furi_hal_nfc_ll_poll(); void furi_hal_nfc_ll_poll();
void furi_hal_nfc_gen_bitstream(FuriHalNfcTxRxContext* tx_rx, uint8_t *buffer, size_t len);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@@ -6,7 +6,6 @@
#define TAG "NfcWorker" #define TAG "NfcWorker"
/***************************** NFC Worker API *******************************/ /***************************** NFC Worker API *******************************/
NfcWorker* nfc_worker_alloc() { NfcWorker* nfc_worker_alloc() {
@@ -94,8 +93,6 @@ int32_t nfc_worker_task(void* context) {
nfc_worker_read(nfc_worker); nfc_worker_read(nfc_worker);
} else if(nfc_worker->state == NfcWorkerStateUidEmulate) { } else if(nfc_worker->state == NfcWorkerStateUidEmulate) {
nfc_worker_emulate_uid(nfc_worker); nfc_worker_emulate_uid(nfc_worker);
} else if(nfc_worker->state == NfcWorkerStateNfcVEmulate) {
nfc_worker_emulate_nfcv(nfc_worker);
} else if(nfc_worker->state == NfcWorkerStateEmulateApdu) { } else if(nfc_worker->state == NfcWorkerStateEmulateApdu) {
nfc_worker_emulate_apdu(nfc_worker); nfc_worker_emulate_apdu(nfc_worker);
} else if(nfc_worker->state == NfcWorkerStateMfUltralightEmulate) { } else if(nfc_worker->state == NfcWorkerStateMfUltralightEmulate) {
@@ -112,6 +109,8 @@ int32_t nfc_worker_task(void* context) {
nfc_worker_mf_classic_dict_attack(nfc_worker); nfc_worker_mf_classic_dict_attack(nfc_worker);
} else if(nfc_worker->state == NfcWorkerStateAnalyzeReader) { } else if(nfc_worker->state == NfcWorkerStateAnalyzeReader) {
nfc_worker_analyze_reader(nfc_worker); nfc_worker_analyze_reader(nfc_worker);
} else if(nfc_worker->state == NfcWorkerStateNfcVEmulate) {
nfc_worker_emulate_nfcv(nfc_worker);
} else if(nfc_worker->state == NfcWorkerStateNfcVUnlock) { } else if(nfc_worker->state == NfcWorkerStateNfcVUnlock) {
nfc_worker_nfcv_unlock(nfc_worker); nfc_worker_nfcv_unlock(nfc_worker);
} else if(nfc_worker->state == NfcWorkerStateNfcVUnlockAndSave) { } else if(nfc_worker->state == NfcWorkerStateNfcVUnlockAndSave) {
@@ -894,98 +893,8 @@ void nfc_worker_emulate_mf_classic(NfcWorker* nfc_worker) {
} }
nfca_signal_free(nfca_signal); nfca_signal_free(nfca_signal);
}
/* software-defined variant of MFC emulation, seems to also struggle with frame errors etc */
void nfc_worker_emulate_mf_classic_trans(NfcWorker* nfc_worker) {
FuriHalNfcTxRxContext tx_rx = {};
FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data;
MfClassicEmulator emulator = {
.cuid = nfc_util_bytes2num(&nfc_data->uid[nfc_data->uid_len - 4], 4),
.data = nfc_worker->dev_data->mf_classic_data,
.data_changed = false,
};
NfcaSignal* nfca_signal = nfca_signal_alloc();
tx_rx.nfca_signal = nfca_signal;
rfal_platform_spi_acquire();
furi_hal_nfc_listen_start(nfc_data);
nfca_trans_rx_init(&tx_rx.nfca_trans_state);
/* we are usingthe fully transparent ISO14443-A mode */
tx_rx.tx_rx_type = FuriHalNfcTxRxFullyTransparent;
/* prepare some answers to save time */
uint8_t tx_buffer_aticoll[32];
memcpy(tx_buffer_aticoll, &nfc_data->uid, 4);
nfca_append_crc16(tx_buffer_aticoll, 4);
uint8_t tx_buffer_ack[8];
tx_buffer_ack[0] = nfc_data->sak;
nfca_append_crc16(tx_buffer_ack, 1);
while(nfc_worker->state == NfcWorkerStateMfClassicEmulate) {
tx_rx.tx_bits = 0;
tx_rx.rx_bits = 0;
if(furi_hal_nfc_tx_rx(&tx_rx, 300)) {
if(tx_rx.rx_bits == 7) {
switch(tx_rx.rx_data[0]) {
/* MAGIC WUPC1 */
case 0x40:
continue;
/* WUPA */
case 0x52:
furi_hal_nfc_gen_bitstream(&tx_rx, nfc_data->atqa, 2);
furi_hal_nfc_tx_rx(&tx_rx, 0);
continue;
}
}
if(tx_rx.rx_bits >= 16) {
switch(tx_rx.rx_data[0]) {
/* SELECT */
case 0x93:
switch(tx_rx.rx_data[1]) {
/* ANTICOLL */
case 0x20:
furi_hal_nfc_gen_bitstream(&tx_rx, tx_buffer_aticoll, 6);
furi_hal_nfc_tx_rx(&tx_rx, 0);
continue;
/* SELECT UID */
case 0x70:
furi_hal_nfc_gen_bitstream(&tx_rx, tx_buffer_ack, 3);
furi_hal_nfc_tx_rx(&tx_rx, 0);
continue;
}
break;
/* HALS */
case 0x50:
continue;
}
}
mf_classic_emulator(&emulator, &tx_rx);
}
}
if(emulator.data_changed) {
nfc_worker->dev_data->mf_classic_data = emulator.data;
if(nfc_worker->callback) {
nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context);
}
emulator.data_changed = false;
}
nfca_trans_rx_deinit(&tx_rx.nfca_trans_state);
rfal_platform_spi_release(); rfal_platform_spi_release();
nfca_signal_free(nfca_signal);
} }
void nfc_worker_write_mf_classic(NfcWorker* nfc_worker) { void nfc_worker_write_mf_classic(NfcWorker* nfc_worker) {

View File

@@ -93,3 +93,4 @@ void nfc_worker_start(
void nfc_worker_stop(NfcWorker* nfc_worker); void nfc_worker_stop(NfcWorker* nfc_worker);
void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker); void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker);
void nfc_worker_emulate_nfcv(NfcWorker* nfc_worker); void nfc_worker_emulate_nfcv(NfcWorker* nfc_worker);

View File

@@ -12,7 +12,6 @@
#include <lib/nfc/protocols/mifare_classic.h> #include <lib/nfc/protocols/mifare_classic.h>
#include <lib/nfc/protocols/mifare_desfire.h> #include <lib/nfc/protocols/mifare_desfire.h>
#include <lib/nfc/protocols/nfca.h> #include <lib/nfc/protocols/nfca.h>
#include <lib/nfc/protocols/nfca_trans_rx.h>
#include <lib/nfc/protocols/nfcv.h> #include <lib/nfc/protocols/nfcv.h>
#include <lib/nfc/protocols/slix.h> #include <lib/nfc/protocols/slix.h>
#include <lib/nfc/helpers/reader_analyzer.h> #include <lib/nfc/helpers/reader_analyzer.h>

View File

@@ -2,27 +2,19 @@
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <furi.h> #include <furi.h>
#include <furi_hal_gpio.h>
#include <furi_hal_resources.h>
#define NFCA_CMD_RATS (0xE0U) #define NFCA_CMD_RATS (0xE0U)
#define NFCA_CRC_INIT (0x6363) #define NFCA_CRC_INIT (0x6363)
#define NFCA_F_SIG (13560000.0) /* [Hz] NFC frequency */ #define NFCA_F_SIG (13560000.0)
#define NFCA_F_SUB (NFCA_F_SIG/16) /* [Hz] NFC subcarrier frequency fs/16 (847500 Hz) */ #define T_SIG 7374 //73.746ns*100
#define T_SUB (1000000000000.0f / NFCA_F_SUB) /* [ps] subcarrier period = 1/NFCA_F_SUB (1.18 µs) */ #define T_SIG_x8 58992 //T_SIG*8
#define T_SUB_PHASE (T_SUB/2) /* [ps] a single subcarrier phase (590 µs) */ #define T_SIG_x8_x8 471936 //T_SIG*8*8
#define T_SIG_x8_x9 530928 //T_SIG*8*9
#define NFCA_SIGNAL_MAX_EDGES (1350) #define NFCA_SIGNAL_MAX_EDGES (1350)
#define SEQ_SOF 0
#define SEQ_BIT0 1
#define SEQ_BIT1 2
#define SEQ_EOF 3
#define SEQ_IDLE 4
typedef struct { typedef struct {
uint8_t cmd; uint8_t cmd;
uint8_t param; uint8_t param;
@@ -71,69 +63,46 @@ bool nfca_emulation_handler(
return sleep; return sleep;
} }
static void nfca_add_bit(DigitalSignal* signal, bool bit) {
if(bit) {
signal->start_level = true;
for(size_t i = 0; i < 7; i++) {
signal->edge_timings[i] = T_SIG_x8;
}
signal->edge_timings[7] = T_SIG_x8_x9;
signal->edge_cnt = 8;
} else {
signal->start_level = false;
signal->edge_timings[0] = T_SIG_x8_x8;
for(size_t i = 1; i < 9; i++) {
signal->edge_timings[i] = T_SIG_x8;
}
signal->edge_cnt = 9;
}
}
static void nfca_add_byte(NfcaSignal* nfca_signal, uint8_t byte, bool parity) { static void nfca_add_byte(NfcaSignal* nfca_signal, uint8_t byte, bool parity) {
for(uint8_t i = 0; i < 8; i++) { for(uint8_t i = 0; i < 8; i++) {
if(byte & (1 << i)) { if(byte & (1 << i)) {
digital_sequence_add(nfca_signal->tx_signal, SEQ_BIT1); digital_signal_append(nfca_signal->tx_signal, nfca_signal->one);
} else { } else {
digital_sequence_add(nfca_signal->tx_signal, SEQ_BIT0); digital_signal_append(nfca_signal->tx_signal, nfca_signal->zero);
} }
} }
if(parity) { if(parity) {
digital_sequence_add(nfca_signal->tx_signal, SEQ_BIT1); digital_signal_append(nfca_signal->tx_signal, nfca_signal->one);
} else { } else {
digital_sequence_add(nfca_signal->tx_signal, SEQ_BIT0); digital_signal_append(nfca_signal->tx_signal, nfca_signal->zero);
}
}
static void nfca_add_modulation(DigitalSignal* signal, size_t phases) {
for(size_t i = 0; i < phases; i++) {
signal->edge_timings[signal->edge_cnt++] = DIGITAL_SIGNAL_PS(T_SUB_PHASE);
}
}
static void nfca_add_silence(DigitalSignal* signal, size_t phases) {
bool end_level = signal->start_level ^ ((signal->edge_cnt % 2) == 0);
if((signal->edge_cnt == 0) || end_level) {
signal->edge_timings[signal->edge_cnt++] = DIGITAL_SIGNAL_PS(phases * T_SUB_PHASE);
} else {
signal->edge_timings[signal->edge_cnt - 1] += DIGITAL_SIGNAL_PS(phases * T_SUB_PHASE);
} }
} }
NfcaSignal* nfca_signal_alloc() { NfcaSignal* nfca_signal_alloc() {
NfcaSignal* nfca_signal = malloc(sizeof(NfcaSignal)); NfcaSignal* nfca_signal = malloc(sizeof(NfcaSignal));
nfca_signal->one = digital_signal_alloc(10);
/* ISO14443-2 defines 3 sequences for type A communication */ nfca_signal->zero = digital_signal_alloc(10);
nfca_signal->seq_d = digital_signal_alloc(10); nfca_add_bit(nfca_signal->one, true);
nfca_signal->seq_e = digital_signal_alloc(10); nfca_add_bit(nfca_signal->zero, false);
nfca_signal->seq_f = digital_signal_alloc(10); nfca_signal->tx_signal = digital_signal_alloc(NFCA_SIGNAL_MAX_EDGES);
/* SEQ D has the first half modulated, used as SOF */
nfca_signal->seq_d->start_level = true;
nfca_add_modulation(nfca_signal->seq_d, 8);
nfca_add_silence(nfca_signal->seq_d, 8);
/* SEQ E has the second half modulated */
nfca_signal->seq_e->start_level = false;
nfca_add_silence(nfca_signal->seq_e, 8);
nfca_add_modulation(nfca_signal->seq_e, 8);
/* SEQ F is just no modulation, used as EOF */
nfca_signal->seq_f->start_level = false;
nfca_add_silence(nfca_signal->seq_f, 16);
nfca_signal->tx_signal = digital_sequence_alloc(NFCA_SIGNAL_MAX_EDGES, &gpio_spi_r_mosi);
/* we are dealing with shorter sequences, enable bake-before-sending */
//nfca_signal->tx_signal->bake = true;
digital_sequence_set_signal(nfca_signal->tx_signal, SEQ_SOF, nfca_signal->seq_d);
digital_sequence_set_signal(nfca_signal->tx_signal, SEQ_BIT0, nfca_signal->seq_e);
digital_sequence_set_signal(nfca_signal->tx_signal, SEQ_BIT1, nfca_signal->seq_d);
digital_sequence_set_signal(nfca_signal->tx_signal, SEQ_EOF, nfca_signal->seq_f);
digital_sequence_set_signal(nfca_signal->tx_signal, SEQ_IDLE, nfca_signal->seq_f);
return nfca_signal; return nfca_signal;
} }
@@ -141,10 +110,9 @@ NfcaSignal* nfca_signal_alloc() {
void nfca_signal_free(NfcaSignal* nfca_signal) { void nfca_signal_free(NfcaSignal* nfca_signal) {
furi_assert(nfca_signal); furi_assert(nfca_signal);
digital_signal_free(nfca_signal->seq_d); digital_signal_free(nfca_signal->one);
digital_signal_free(nfca_signal->seq_e); digital_signal_free(nfca_signal->zero);
digital_signal_free(nfca_signal->seq_f); digital_signal_free(nfca_signal->tx_signal);
digital_sequence_free(nfca_signal->tx_signal);
free(nfca_signal); free(nfca_signal);
} }
@@ -153,18 +121,17 @@ void nfca_signal_encode(NfcaSignal* nfca_signal, uint8_t* data, uint16_t bits, u
furi_assert(data); furi_assert(data);
furi_assert(parity); furi_assert(parity);
digital_sequence_clear(nfca_signal->tx_signal); nfca_signal->tx_signal->edge_cnt = 0;
nfca_signal->tx_signal->start_level = true;
/* add some idle bit times before SOF in case the GPIO was active */ // Start of frame
digital_sequence_add(nfca_signal->tx_signal, SEQ_IDLE); digital_signal_append(nfca_signal->tx_signal, nfca_signal->one);
digital_sequence_add(nfca_signal->tx_signal, SEQ_SOF);
if(bits < 8) { if(bits < 8) {
for(size_t i = 0; i < bits; i++) { for(size_t i = 0; i < bits; i++) {
if(FURI_BIT(data[0], i)) { if(FURI_BIT(data[0], i)) {
digital_sequence_add(nfca_signal->tx_signal, SEQ_BIT1); digital_signal_append(nfca_signal->tx_signal, nfca_signal->one);
} else { } else {
digital_sequence_add(nfca_signal->tx_signal, SEQ_BIT0); digital_signal_append(nfca_signal->tx_signal, nfca_signal->zero);
} }
} }
} else { } else {
@@ -172,6 +139,4 @@ void nfca_signal_encode(NfcaSignal* nfca_signal, uint8_t* data, uint16_t bits, u
nfca_add_byte(nfca_signal, data[i], parity[i / 8] & (1 << (7 - (i & 0x07)))); nfca_add_byte(nfca_signal, data[i], parity[i / 8] & (1 << (7 - (i & 0x07))));
} }
} }
digital_sequence_add(nfca_signal->tx_signal, SEQ_EOF);
} }

View File

@@ -6,10 +6,9 @@
#include <lib/digital_signal/digital_signal.h> #include <lib/digital_signal/digital_signal.h>
typedef struct { typedef struct {
DigitalSignal* seq_d; /* sequence D, modulation with subcarrier during first half */ DigitalSignal* one;
DigitalSignal* seq_e; /* sequence E, modulation with subcarrier during second half */ DigitalSignal* zero;
DigitalSignal* seq_f; /* sequence F, no modulation at all */ DigitalSignal* tx_signal;
DigitalSequence* tx_signal;
} NfcaSignal; } NfcaSignal;
uint16_t nfca_get_crc16(uint8_t* buff, uint16_t len); uint16_t nfca_get_crc16(uint8_t* buff, uint16_t len);