added ISO14443 tag emulator code, receiving only yet

This commit is contained in:
g3gg0
2022-11-24 01:43:23 +01:00
parent 1dc4069756
commit 674a5c6f48
2 changed files with 214 additions and 0 deletions
+167
View File
@@ -0,0 +1,167 @@
#include <limits.h>
#include <furi.h>
#include <furi_hal.h>
#include <furi_hal_nfc.h>
#include <furi_hal_spi.h>
#include <furi_hal_gpio.h>
#include <furi_hal_cortex.h>
#include <furi_hal_resources.h>
#include <st25r3916.h>
#include <st25r3916_irq.h>
#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;
}
+47
View File
@@ -0,0 +1,47 @@
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include <lib/digital_signal/digital_signal.h>
#include <lib/pulse_reader/pulse_reader.h>
#include <furi_hal_nfc.h>
#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);