From 674a5c6f48793737dc3cb2e1e638b9128298b715 Mon Sep 17 00:00:00 2001 From: g3gg0 Date: Thu, 24 Nov 2022 01:43:23 +0100 Subject: [PATCH] added ISO14443 tag emulator code, receiving only yet --- lib/nfc/protocols/nfca_emu.c | 167 +++++++++++++++++++++++++++++++++++ lib/nfc/protocols/nfca_emu.h | 47 ++++++++++ 2 files changed, 214 insertions(+) create mode 100644 lib/nfc/protocols/nfca_emu.c create mode 100644 lib/nfc/protocols/nfca_emu.h diff --git a/lib/nfc/protocols/nfca_emu.c b/lib/nfc/protocols/nfca_emu.c new file mode 100644 index 000000000..6040bad14 --- /dev/null +++ b/lib/nfc/protocols/nfca_emu.c @@ -0,0 +1,167 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "nfca_emu.h" + +#define TAG "NfcA-emu" + + + + +void nfca_emu_init(NfcaEmuState *state, FuriHalNfcDevData* nfc_data) { + //nfca_emu_alloc(); + rfal_platform_spi_acquire(); + + st25r3916ExecuteCommand(ST25R3916_CMD_STOP); + st25r3916WriteRegister(ST25R3916_REG_OP_CONTROL, 0xC3); + st25r3916WriteRegister(ST25R3916_REG_MODE, 0x88); + st25r3916ExecuteCommand(ST25R3916_CMD_TRANSPARENT_MODE); + + furi_hal_spi_bus_handle_deinit(&furi_hal_spi_bus_handle_nfc); + + FURI_LOG_D(TAG, "Starting NfcA emulation"); + FURI_LOG_D(TAG, " UID: %02X %02X %02X %02X %02X %02X %02X %02X", + nfc_data->uid[0], nfc_data->uid[1], nfc_data->uid[2], nfc_data->uid[3], + nfc_data->uid[4], nfc_data->uid[5], nfc_data->uid[6], nfc_data->uid[7]); + + /* allocate a 512 edge buffer, more than enough */ + state->reader_signal = pulse_reader_alloc(&gpio_spi_r_miso, 512); + /* timebase shall be 1 ns */ + pulse_reader_set_timebase(state->reader_signal, PulseReaderUnitNanosecond); + + pulse_reader_start(state->reader_signal); + + /* set start values */ + state->bits_received = 0; + state->have_sof = false; + state->valid_frame = false; +} + +void nfca_emu_deinit(NfcaEmuState *state) { + furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc); + rfal_platform_spi_release(); + pulse_reader_free(state->reader_signal); +} + + +void nfca_bit_received(NfcaEmuState *state, uint8_t bit) { + + /* According to ISO14443-3 short frames have 7 bits and standard 9 bits per byte, + where the 9th bit is odd parity. Data is transmitted LSB first. */ + uint32_t byte_num = (state->bits_received / 9); + uint32_t bit_num = (state->bits_received % 9); + + if(bit_num == 8) { + uint32_t parity_value = 1 << (state->bits_received / 9); + state->parity_bits &= ~parity_value; + state->parity_bits |= bit ? parity_value : 0; + } else { + uint32_t bit_value = 1 << bit_num; + state->frame_data[byte_num] &= ~bit_value; + state->frame_data[byte_num] |= bit ? bit_value : 0; + } + + state->bits_received++; +} + + +bool nfca_emu_loop(NfcaEmuState *state, FuriHalNfcDevData* nfc_data, uint32_t timeout_ms) { + furi_assert(nfc_data); + + bool ret = false; + + while(!ret) { + uint32_t timeout_ns = timeout_ms * 1000; + uint32_t timeout = state->have_sof ? (4 * NFCA_TB) : timeout_ns; + uint32_t nsec = pulse_reader_receive(state->reader_signal, timeout); + + + bool eof = state->have_sof && nsec > 2*NFCA_TB; + + if(nsec != PULSE_READER_NO_EDGE) { + FURI_LOG_T(TAG, "pulse: %lu ns, frametime now: %ld", nsec, state->frame_time); + } + + if(IS_T1(nsec) || eof) { + FURI_LOG_T(TAG, " T1 pulse"); + + if(!state->have_sof) { + FURI_LOG_T(TAG, " SOF"); + state->frame_time = -(NFCA_TB - nsec); + state->have_sof = true; + state->valid_frame = false; + state->bits_received = 0; + continue; + } + + if(state->frame_time > NFCA_TB_MIN) { + FURI_LOG_T(TAG, " Y"); + state->frame_time -= NFCA_TB; + nfca_bit_received(state, 0); + } + + if(IS_ZERO(state->frame_time)) { + FURI_LOG_T(TAG, " Z"); + state->frame_time = -(NFCA_TB - nsec); + nfca_bit_received(state, 0); + } else if(IS_TX(state->frame_time)) { + FURI_LOG_T(TAG, " X"); + state->frame_time = -(NFCA_TX - nsec); + nfca_bit_received(state, 1); + } else { + if(eof) { + FURI_LOG_T(TAG, " EOF"); + state->have_sof = false; + state->valid_frame = true; + ret = true; + } else { + FURI_LOG_D(TAG, " unexpected: %ld", state->frame_time); + } + } + + + } else { + if(!state->have_sof) { + state->frame_time = 0; + } else { + state->frame_time += nsec; + FURI_LOG_T(TAG, " non-T1 pulse"); + } + } + } + + if(ret) { + + if(state->bits_received > 7) { + /* a last 0-bit will look like a missing bit */ + if((state->bits_received % 9) == 8) { + nfca_bit_received(state, 0); + state->bits_received++; + } + FURI_LOG_D(TAG, "Received standard frame: %d bits (%d byte)", state->bits_received, state->bits_received/9); + + for(size_t pos = 0; pos < state->bits_received / 9; pos++) { + FURI_LOG_D(TAG, " 0x%02X", state->frame_data[pos]); + } + } else { + FURI_LOG_D(TAG, "Received short frame: %d bits", state->bits_received); + FURI_LOG_D(TAG, " 0x%02X", state->frame_data[0] & 0x7F); + } + + /* we know that this code uses TIM2, so stop pulse reader */ + //pulse_reader_stop(state->reader_signal); + //nfcv_emu_handle_packet(nfc_data, nfcv_data, frame_payload, frame_pos); + //pulse_reader_start(state->reader_signal); + } + + return ret; +} diff --git a/lib/nfc/protocols/nfca_emu.h b/lib/nfc/protocols/nfca_emu.h new file mode 100644 index 000000000..8fc769da5 --- /dev/null +++ b/lib/nfc/protocols/nfca_emu.h @@ -0,0 +1,47 @@ +#pragma once + +#include +#include + +#include +#include +#include + +#include "nfc_util.h" + +/* assume fc/128 */ +#define NFCA_FC (13560000.0f) /* MHz */ +#define NFCA_FC_K ((uint32_t)(NFCA_FC/1000)) /* kHz */ +#define NFCA_T1_MIN (24.0f / NFCA_FC * 1000000000) +#define NFCA_T1_MAX (41.0f / NFCA_FC * 1000000000) +#define NFCA_TX (64.0f / NFCA_FC * 1000000000) /* 4.7198 µs */ +#define NFCA_TX_MIN (0.90f * NFCA_TX) +#define NFCA_TX_MAX (1.10f * NFCA_TX) +#define NFCA_TB (128.0f / NFCA_FC * 1000000000) /* 9.4395 µs */ +#define NFCA_TB_MIN (0.80f * NFCA_TB) +#define NFCA_TB_MAX (1.20f * NFCA_TB) + +#define IS_T1(x) ((x)>=NFCA_T1_MIN && (x)<=NFCA_T1_MAX) +#define IS_TX(x) ((x)>=NFCA_TX_MIN && (x)<=NFCA_TX_MAX) +#define IS_TB(x) ((x)>=NFCA_TB_MIN && (x)<=NFCA_TB_MAX) +#define IS_ZERO(x) ((x)>=-NFCA_T1_MIN/2 && (x)<=NFCA_T1_MIN/2) + +#define DIGITAL_SIGNAL_UNIT_S (100000000000.0f) +#define DIGITAL_SIGNAL_UNIT_US (100000.0f) + +#define NFCA_FRAME_LENGTH 32 + + +typedef struct { + bool have_sof; + bool valid_frame; + int32_t frame_time; + size_t bits_received; + uint8_t frame_data[NFCA_FRAME_LENGTH]; + uint32_t parity_bits; + PulseReader *reader_signal; +} NfcaEmuState; + +bool nfca_emu_loop(NfcaEmuState *state, FuriHalNfcDevData* nfc_data, uint32_t timeout_ms); +void nfca_emu_deinit(NfcaEmuState *state); +void nfca_emu_init(NfcaEmuState *state, FuriHalNfcDevData* nfc_data);