mirror of
https://github.com/DarkFlippers/unleashed-firmware
synced 2024-11-30 16:29:12 +00:00
d92b0a82cc
"A long time ago in a galaxy far, far away...." we started NFC subsystem refactoring. Starring: - @gornekich - NFC refactoring project lead, architect, senior developer - @gsurkov - architect, senior developer - @RebornedBrain - senior developer Supporting roles: - @skotopes, @DrZlo13, @hedger - general architecture advisors, code review - @Astrrra, @doomwastaken, @Hellitron, @ImagineVagon333 - quality assurance Special thanks: @bettse, @pcunning, @nxv, @noproto, @AloneLiberty and everyone else who has been helping us all this time and contributing valuable knowledges, ideas and source code.
204 lines
7.2 KiB
C
204 lines
7.2 KiB
C
#include "iso15693_signal.h"
|
|
|
|
#include <digital_signal/digital_sequence.h>
|
|
|
|
#define BITS_IN_BYTE (8U)
|
|
|
|
#define ISO15693_SIGNAL_COEFF_HI (1U)
|
|
#define ISO15693_SIGNAL_COEFF_LO (4U)
|
|
|
|
#define ISO15693_SIGNAL_ZERO_EDGES (16U)
|
|
#define ISO15693_SIGNAL_ONE_EDGES (ISO15693_SIGNAL_ZERO_EDGES + 1U)
|
|
#define ISO15693_SIGNAL_EOF_EDGES (64U)
|
|
#define ISO15693_SIGNAL_SOF_EDGES (ISO15693_SIGNAL_EOF_EDGES + 1U)
|
|
#define ISO15693_SIGNAL_EDGES (1350U)
|
|
|
|
#define ISO15693_SIGNAL_FC (13.56e6)
|
|
#define ISO15693_SIGNAL_FC_16 (16.0e11 / ISO15693_SIGNAL_FC)
|
|
#define ISO15693_SIGNAL_FC_256 (256.0e11 / ISO15693_SIGNAL_FC)
|
|
#define ISO15693_SIGNAL_FC_768 (768.0e11 / ISO15693_SIGNAL_FC)
|
|
|
|
typedef enum {
|
|
Iso15693SignalIndexSof,
|
|
Iso15693SignalIndexEof,
|
|
Iso15693SignalIndexOne,
|
|
Iso15693SignalIndexZero,
|
|
Iso15693SignalIndexNum,
|
|
} Iso15693SignalIndex;
|
|
|
|
typedef DigitalSignal* Iso15693SignalBank[Iso15693SignalIndexNum];
|
|
|
|
struct Iso15693Signal {
|
|
DigitalSequence* tx_sequence;
|
|
Iso15693SignalBank banks[Iso15693SignalDataRateNum];
|
|
};
|
|
|
|
// Add an unmodulated signal for the length of Fc / 256 * k (where k = 1 or 4)
|
|
static void iso15693_add_silence(DigitalSignal* signal, Iso15693SignalDataRate data_rate) {
|
|
const uint32_t k = data_rate == Iso15693SignalDataRateHi ? ISO15693_SIGNAL_COEFF_HI :
|
|
ISO15693_SIGNAL_COEFF_LO;
|
|
digital_signal_add_period_with_level(signal, ISO15693_SIGNAL_FC_256 * k, false);
|
|
}
|
|
|
|
// Add 8 * k subcarrier pulses of Fc / 16 (where k = 1 or 4)
|
|
static void iso15693_add_subcarrier(DigitalSignal* signal, Iso15693SignalDataRate data_rate) {
|
|
const uint32_t k = data_rate == Iso15693SignalDataRateHi ? ISO15693_SIGNAL_COEFF_HI :
|
|
ISO15693_SIGNAL_COEFF_LO;
|
|
for(uint32_t i = 0; i < ISO15693_SIGNAL_ZERO_EDGES * k; ++i) {
|
|
digital_signal_add_period_with_level(signal, ISO15693_SIGNAL_FC_16, !(i % 2));
|
|
}
|
|
}
|
|
|
|
static void iso15693_add_bit(DigitalSignal* signal, Iso15693SignalDataRate data_rate, bool bit) {
|
|
if(bit) {
|
|
iso15693_add_silence(signal, data_rate);
|
|
iso15693_add_subcarrier(signal, data_rate);
|
|
} else {
|
|
iso15693_add_subcarrier(signal, data_rate);
|
|
iso15693_add_silence(signal, data_rate);
|
|
}
|
|
}
|
|
|
|
static inline void iso15693_add_sof(DigitalSignal* signal, Iso15693SignalDataRate data_rate) {
|
|
// Not adding silence since it only increases response time
|
|
|
|
for(uint32_t i = 0; i < ISO15693_SIGNAL_FC_768 / ISO15693_SIGNAL_FC_256; ++i) {
|
|
iso15693_add_subcarrier(signal, data_rate);
|
|
}
|
|
|
|
iso15693_add_bit(signal, data_rate, true);
|
|
}
|
|
|
|
static inline void iso15693_add_eof(DigitalSignal* signal, Iso15693SignalDataRate data_rate) {
|
|
iso15693_add_bit(signal, data_rate, false);
|
|
|
|
for(uint32_t i = 0; i < ISO15693_SIGNAL_FC_768 / ISO15693_SIGNAL_FC_256; ++i) {
|
|
iso15693_add_subcarrier(signal, data_rate);
|
|
}
|
|
|
|
// Not adding silence since it does nothing here
|
|
}
|
|
|
|
static inline uint32_t
|
|
iso15693_get_sequence_index(Iso15693SignalIndex index, Iso15693SignalDataRate data_rate) {
|
|
return index + data_rate * Iso15693SignalIndexNum;
|
|
}
|
|
|
|
static inline void
|
|
iso15693_add_byte(Iso15693Signal* instance, Iso15693SignalDataRate data_rate, uint8_t byte) {
|
|
for(size_t i = 0; i < BITS_IN_BYTE; i++) {
|
|
const uint8_t bit = byte & (1U << i);
|
|
digital_sequence_add_signal(
|
|
instance->tx_sequence,
|
|
iso15693_get_sequence_index(
|
|
bit ? Iso15693SignalIndexOne : Iso15693SignalIndexZero, data_rate));
|
|
}
|
|
}
|
|
|
|
static inline void iso15693_signal_encode(
|
|
Iso15693Signal* instance,
|
|
Iso15693SignalDataRate data_rate,
|
|
const uint8_t* tx_data,
|
|
size_t tx_data_size) {
|
|
digital_sequence_add_signal(
|
|
instance->tx_sequence, iso15693_get_sequence_index(Iso15693SignalIndexSof, data_rate));
|
|
|
|
for(size_t i = 0; i < tx_data_size; i++) {
|
|
iso15693_add_byte(instance, data_rate, tx_data[i]);
|
|
}
|
|
|
|
digital_sequence_add_signal(
|
|
instance->tx_sequence, iso15693_get_sequence_index(Iso15693SignalIndexEof, data_rate));
|
|
}
|
|
|
|
static void iso15693_signal_bank_fill(Iso15693Signal* instance, Iso15693SignalDataRate data_rate) {
|
|
const uint32_t k = data_rate == Iso15693SignalDataRateHi ? ISO15693_SIGNAL_COEFF_HI :
|
|
ISO15693_SIGNAL_COEFF_LO;
|
|
DigitalSignal** bank = instance->banks[data_rate];
|
|
|
|
bank[Iso15693SignalIndexSof] = digital_signal_alloc(ISO15693_SIGNAL_SOF_EDGES * k);
|
|
bank[Iso15693SignalIndexEof] = digital_signal_alloc(ISO15693_SIGNAL_EOF_EDGES * k);
|
|
bank[Iso15693SignalIndexOne] = digital_signal_alloc(ISO15693_SIGNAL_ONE_EDGES * k);
|
|
bank[Iso15693SignalIndexZero] = digital_signal_alloc(ISO15693_SIGNAL_ZERO_EDGES * k);
|
|
|
|
iso15693_add_sof(bank[Iso15693SignalIndexSof], data_rate);
|
|
iso15693_add_eof(bank[Iso15693SignalIndexEof], data_rate);
|
|
iso15693_add_bit(bank[Iso15693SignalIndexOne], data_rate, true);
|
|
iso15693_add_bit(bank[Iso15693SignalIndexZero], data_rate, false);
|
|
}
|
|
|
|
static void
|
|
iso15693_signal_bank_clear(Iso15693Signal* instance, Iso15693SignalDataRate data_rate) {
|
|
DigitalSignal** bank = instance->banks[data_rate];
|
|
|
|
for(uint32_t i = 0; i < Iso15693SignalIndexNum; ++i) {
|
|
digital_signal_free(bank[i]);
|
|
}
|
|
}
|
|
|
|
static void
|
|
iso15693_signal_bank_register(Iso15693Signal* instance, Iso15693SignalDataRate data_rate) {
|
|
for(uint32_t i = 0; i < Iso15693SignalIndexNum; ++i) {
|
|
digital_sequence_register_signal(
|
|
instance->tx_sequence,
|
|
iso15693_get_sequence_index(i, data_rate),
|
|
instance->banks[data_rate][i]);
|
|
}
|
|
}
|
|
|
|
Iso15693Signal* iso15693_signal_alloc(const GpioPin* pin) {
|
|
furi_assert(pin);
|
|
|
|
Iso15693Signal* instance = malloc(sizeof(Iso15693Signal));
|
|
|
|
instance->tx_sequence = digital_sequence_alloc(BITS_IN_BYTE * 255 + 2, pin);
|
|
|
|
for(uint32_t i = 0; i < Iso15693SignalDataRateNum; ++i) {
|
|
iso15693_signal_bank_fill(instance, i);
|
|
iso15693_signal_bank_register(instance, i);
|
|
}
|
|
|
|
return instance;
|
|
}
|
|
|
|
void iso15693_signal_free(Iso15693Signal* instance) {
|
|
furi_assert(instance);
|
|
|
|
digital_sequence_free(instance->tx_sequence);
|
|
|
|
for(uint32_t i = 0; i < Iso15693SignalDataRateNum; ++i) {
|
|
iso15693_signal_bank_clear(instance, i);
|
|
}
|
|
|
|
free(instance);
|
|
}
|
|
|
|
void iso15693_signal_tx(
|
|
Iso15693Signal* instance,
|
|
Iso15693SignalDataRate data_rate,
|
|
const uint8_t* tx_data,
|
|
size_t tx_data_size) {
|
|
furi_assert(instance);
|
|
furi_assert(data_rate < Iso15693SignalDataRateNum);
|
|
furi_assert(tx_data);
|
|
|
|
FURI_CRITICAL_ENTER();
|
|
digital_sequence_clear(instance->tx_sequence);
|
|
iso15693_signal_encode(instance, data_rate, tx_data, tx_data_size);
|
|
digital_sequence_transmit(instance->tx_sequence);
|
|
|
|
FURI_CRITICAL_EXIT();
|
|
}
|
|
|
|
void iso15693_signal_tx_sof(Iso15693Signal* instance, Iso15693SignalDataRate data_rate) {
|
|
furi_assert(instance);
|
|
furi_assert(data_rate < Iso15693SignalDataRateNum);
|
|
|
|
FURI_CRITICAL_ENTER();
|
|
digital_sequence_clear(instance->tx_sequence);
|
|
digital_sequence_add_signal(
|
|
instance->tx_sequence, iso15693_get_sequence_index(Iso15693SignalIndexSof, data_rate));
|
|
digital_sequence_transmit(instance->tx_sequence);
|
|
|
|
FURI_CRITICAL_EXIT();
|
|
}
|