diff --git a/applications/main/nfc/helpers/protocol_support/iso15693_3/iso15693_3.c b/applications/main/nfc/helpers/protocol_support/iso15693_3/iso15693_3.c index 0547911f7142..57a73cc0ca3f 100644 --- a/applications/main/nfc/helpers/protocol_support/iso15693_3/iso15693_3.c +++ b/applications/main/nfc/helpers/protocol_support/iso15693_3/iso15693_3.c @@ -110,7 +110,8 @@ static bool nfc_scene_saved_menu_on_event_iso15693_3(NfcApp* instance, uint32_t } const NfcProtocolSupportBase nfc_protocol_support_iso15693_3 = { - .features = NfcProtocolFeatureEmulateFull, // | NfcProtocolFeatureEditUid, // TODO: Implement better UID editing + .features = + NfcProtocolFeatureEmulateFull, // | NfcProtocolFeatureEditUid, // TODO: Implement better UID editing .scene_info = { diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index ea918d823cda..121d95fc9340 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,35.0,, +Version,+,36.2,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -182,6 +182,7 @@ Header,+,lib/one_wire/one_wire_host.h,, Header,+,lib/one_wire/one_wire_slave.h,, Header,+,lib/print/wrappers.h,, Header,+,lib/pulse_reader/pulse_reader.h,, +Header,+,lib/signal_reader/signal_reader.h,, Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_adc.h,, Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_bus.h,, Header,+,lib/stm32wb_hal/Inc/stm32wbxx_ll_comp.h,, @@ -871,7 +872,6 @@ Function,-,expm1l,long double,long double Function,-,f_hal_nfc_abort,FHalNfcError, Function,-,f_hal_nfc_acquire,FHalNfcError, Function,+,f_hal_nfc_event_start,FHalNfcError, -Function,+,f_hal_nfc_event_wait,FHalNfcEvent,uint32_t Function,-,f_hal_nfc_init,FHalNfcError, Function,-,f_hal_nfc_is_hal_ready,FHalNfcError, Function,-,f_hal_nfc_listener_disable_auto_col_res,FHalNfcError, @@ -881,12 +881,14 @@ Function,+,f_hal_nfc_listener_rx_start,FHalNfcError, Function,-,f_hal_nfc_listener_sleep,FHalNfcError, Function,+,f_hal_nfc_listener_start,FHalNfcError, Function,-,f_hal_nfc_listener_tx,FHalNfcError,"const uint8_t*, size_t" +Function,-,f_hal_nfc_listener_wait_event,FHalNfcEvent,uint32_t Function,-,f_hal_nfc_low_power_mode_start,FHalNfcError, Function,-,f_hal_nfc_low_power_mode_stop,FHalNfcError, Function,-,f_hal_nfc_poller_field_on,FHalNfcError, Function,-,f_hal_nfc_poller_rx,FHalNfcError,"uint8_t*, size_t, size_t*" Function,-,f_hal_nfc_poller_tx,FHalNfcError,"const uint8_t*, size_t" Function,-,f_hal_nfc_poller_tx_custom_parity,FHalNfcError,"const uint8_t*, size_t" +Function,-,f_hal_nfc_poller_wait_event,FHalNfcEvent,uint32_t Function,-,f_hal_nfc_release,FHalNfcError, Function,-,f_hal_nfc_reset_mode,FHalNfcError, Function,-,f_hal_nfc_set_mask_receive_timer,void,uint32_t @@ -2667,6 +2669,13 @@ Function,+,sha256_finish,void,"sha256_context*, unsigned char[32]" Function,+,sha256_process,void,sha256_context* Function,+,sha256_start,void,sha256_context* Function,+,sha256_update,void,"sha256_context*, const unsigned char*, unsigned int" +Function,+,signal_reader_alloc,SignalReader*,"const GpioPin*, uint32_t" +Function,+,signal_reader_free,void,SignalReader* +Function,+,signal_reader_set_polarity,void,"SignalReader*, SignalReaderPolarity" +Function,+,signal_reader_set_pull,void,"SignalReader*, GpioPull" +Function,+,signal_reader_set_sample_rate,void,"SignalReader*, SignalReaderTimeUnit, uint32_t" +Function,+,signal_reader_start,void,"SignalReader*, SignalReaderCallback, void*" +Function,+,signal_reader_stop,void,SignalReader* Function,+,simple_array_alloc,SimpleArray*,const SimpleArrayConfig* Function,+,simple_array_cget,const SimpleArrayElement*,"const SimpleArray*, uint32_t" Function,+,simple_array_cget_data,const SimpleArrayData*,const SimpleArray* diff --git a/firmware/targets/f7/furi_hal/f_hal_nfc.c b/firmware/targets/f7/furi_hal/f_hal_nfc.c index 3d3d5ab23bb0..93df25cd1baa 100644 --- a/firmware/targets/f7/furi_hal/f_hal_nfc.c +++ b/firmware/targets/f7/furi_hal/f_hal_nfc.c @@ -433,11 +433,13 @@ FHalNfcError f_hal_nfc_poller_tx_custom_parity(const uint8_t* tx_data, size_t tx return err; } -FHalNfcError f_hal_nfc_poller_tx(const uint8_t* tx_data, size_t tx_bits) { +FHalNfcError f_hal_nfc_poller_tx_common( + FuriHalSpiBusHandle* handle, + const uint8_t* tx_data, + size_t tx_bits) { furi_assert(tx_data); FHalNfcError err = FHalNfcErrorNone; - FuriHalSpiBusHandle* handle = &furi_hal_spi_bus_handle_nfc; // Prepare tx st25r3916_direct_cmd(handle, ST25R3916_CMD_CLEAR_FIFO); @@ -474,6 +476,36 @@ FHalNfcError return err; } +FHalNfcError f_hal_nfc_poller_tx(const uint8_t* tx_data, size_t tx_bits) { + furi_assert(f_hal_nfc.mode == FHalNfcModePoller); + furi_assert(f_hal_nfc.tech < FHalNfcTechNum); + FuriHalSpiBusHandle* handle = &furi_hal_spi_bus_handle_nfc; + + return f_hal_nfc_tech[f_hal_nfc.tech]->poller.tx(handle, tx_data, tx_bits); +} + +FHalNfcError f_hal_nfc_poller_rx(uint8_t* rx_data, size_t rx_data_size, size_t* rx_bits) { + furi_assert(f_hal_nfc.mode == FHalNfcModePoller); + furi_assert(f_hal_nfc.tech < FHalNfcTechNum); + FuriHalSpiBusHandle* handle = &furi_hal_spi_bus_handle_nfc; + + return f_hal_nfc_tech[f_hal_nfc.tech]->poller.rx(handle, rx_data, rx_data_size, rx_bits); +} + +FHalNfcEvent f_hal_nfc_poller_wait_event(uint32_t timeout_ms) { + furi_assert(f_hal_nfc.mode == FHalNfcModePoller); + furi_assert(f_hal_nfc.tech < FHalNfcTechNum); + + return f_hal_nfc_tech[f_hal_nfc.tech]->poller.wait_event(timeout_ms); +} + +FHalNfcEvent f_hal_nfc_listener_wait_event(uint32_t timeout_ms) { + furi_assert(f_hal_nfc.mode == FHalNfcModeListener); + furi_assert(f_hal_nfc.tech < FHalNfcTechNum); + + return f_hal_nfc_tech[f_hal_nfc.tech]->listener.wait_event(timeout_ms); +} + FHalNfcError f_hal_nfc_listener_tx(const uint8_t* tx_data, size_t tx_bits) { furi_assert(tx_data); @@ -523,14 +555,6 @@ FHalNfcError f_hal_nfc_listener_rx(uint8_t* rx_data, size_t rx_data_size, size_t return f_hal_nfc_tech[f_hal_nfc.tech]->listener.rx(handle, rx_data, rx_data_size, rx_bits); } -FHalNfcError f_hal_nfc_poller_rx(uint8_t* rx_data, size_t rx_data_size, size_t* rx_bits) { - furi_assert(rx_data); - furi_assert(rx_bits); - - FuriHalSpiBusHandle* handle = &furi_hal_spi_bus_handle_nfc; - return f_hal_nfc_common_fifo_rx(handle, rx_data, rx_data_size, rx_bits); -} - FHalNfcError f_hal_nfc_trx_reset() { FuriHalSpiBusHandle* handle = &furi_hal_spi_bus_handle_nfc; diff --git a/firmware/targets/f7/furi_hal/f_hal_nfc_event.c b/firmware/targets/f7/furi_hal/f_hal_nfc_event.c index 4b0dc7236098..622038fefa4e 100644 --- a/firmware/targets/f7/furi_hal/f_hal_nfc_event.c +++ b/firmware/targets/f7/furi_hal/f_hal_nfc_event.c @@ -27,7 +27,7 @@ FHalNfcError f_hal_nfc_abort() { return FHalNfcErrorNone; } -FHalNfcEvent f_hal_nfc_event_wait(uint32_t timeout_ms) { +FHalNfcEvent f_hal_nfc_wait_event_common(uint32_t timeout_ms) { furi_assert(f_hal_nfc_event); furi_assert(f_hal_nfc_event->thread); @@ -81,24 +81,6 @@ FHalNfcEvent f_hal_nfc_event_wait(uint32_t timeout_ms) { event |= FHalNfcEventAbortRequest; furi_thread_flags_clear(FHalNfcEventInternalTypeAbort); } - // Transparent mode events - // TODO: Rework transparent mode - if(event_flag & FHalNfcEventInternalTypeTransparentFieldOn) { - event |= FHalNfcEventFieldOn; - furi_thread_flags_clear(FHalNfcEventInternalTypeTransparentFieldOn); - } - if(event_flag & FHalNfcEventInternalTypeTransparentFieldOff) { - event |= FHalNfcEventFieldOff; - furi_thread_flags_clear(FHalNfcEventInternalTypeTransparentFieldOff); - } - if(event_flag & FHalNfcEventInternalTypeTransparentRxEnd) { - event |= FHalNfcEventRxEnd; - furi_thread_flags_clear(FHalNfcEventInternalTypeTransparentRxEnd); - } - if(event_flag & FHalNfcEventInternalTypeTransparentTimeout) { - event |= FHalNfcEventTimeout; - furi_thread_flags_clear(FHalNfcEventInternalTypeTransparentTimeout); - } } else { event = FHalNfcEventTimeout; } diff --git a/firmware/targets/f7/furi_hal/f_hal_nfc_i.h b/firmware/targets/f7/furi_hal/f_hal_nfc_i.h index a486219e0649..fa49826c624b 100644 --- a/firmware/targets/f7/furi_hal/f_hal_nfc_i.h +++ b/firmware/targets/f7/furi_hal/f_hal_nfc_i.h @@ -15,15 +15,13 @@ typedef enum { FHalNfcEventInternalTypeIrq = (1U << 1), FHalNfcEventInternalTypeTimerFwtExpired = (1U << 2), FHalNfcEventInternalTypeTimerBlockTxExpired = (1U << 3), - FHalNfcEventInternalTypeTransparentFieldOn = (1U << 4), - FHalNfcEventInternalTypeTransparentFieldOff = (1U << 5), - FHalNfcEventInternalTypeTransparentRxEnd = (1U << 6), - FHalNfcEventInternalTypeTransparentTimeout = (1U << 7), + FHalNfcEventInternalTypeTransparentDataReceived = (1U << 4), } FHalNfcEventInternalType; -#define F_HAL_NFC_EVENT_INTERNAL_ALL \ - ((FHalNfcEventInternalTypeAbort | FHalNfcEventInternalTypeIrq | \ - FHalNfcEventInternalTypeTimerFwtExpired | FHalNfcEventInternalTypeTimerBlockTxExpired)) +#define F_HAL_NFC_EVENT_INTERNAL_ALL \ + ((FHalNfcEventInternalTypeAbort | FHalNfcEventInternalTypeIrq | \ + FHalNfcEventInternalTypeTimerFwtExpired | FHalNfcEventInternalTypeTimerBlockTxExpired | \ + FHalNfcEventInternalTypeTransparentDataReceived)) typedef struct { FuriThreadId thread; @@ -58,6 +56,7 @@ bool f_hal_nfc_event_wait_for_specific_irq( uint32_t timeout_ms); // Common technology methods +FHalNfcEvent f_hal_nfc_wait_event_common(uint32_t timeout_ms); FHalNfcError f_hal_nfc_common_listener_rx_start(FuriHalSpiBusHandle* handle); FHalNfcError f_hal_nfc_common_fifo_tx(FuriHalSpiBusHandle* handle, const uint8_t* tx_data, size_t tx_bits); @@ -67,27 +66,35 @@ FHalNfcError f_hal_nfc_common_fifo_rx( size_t rx_data_size, size_t* rx_bits); +FHalNfcError + f_hal_nfc_poller_tx_common(FuriHalSpiBusHandle* handle, const uint8_t* tx_data, size_t tx_bits); + // Technology specific API typedef FHalNfcError (*FHalNfcChipConfig)(FuriHalSpiBusHandle* handle); typedef FHalNfcError ( - *FHalNfcChipTx)(FuriHalSpiBusHandle* handle, const uint8_t* tx_data, size_t tx_bits); -typedef FHalNfcError (*FHalNfcChipRx)( + *FHalNfcTx)(FuriHalSpiBusHandle* handle, const uint8_t* tx_data, size_t tx_bits); +typedef FHalNfcError (*FHalNfcRx)( FuriHalSpiBusHandle* handle, uint8_t* rx_data, size_t rx_data_size, size_t* rx_bits); +typedef FHalNfcEvent (*FHalNfcWaitEvent)(uint32_t timeout_ms); typedef struct { FHalNfcChipConfig init; FHalNfcChipConfig deinit; + FHalNfcWaitEvent wait_event; + FHalNfcTx tx; + FHalNfcRx rx; } FHalNfcTechPollerBase; typedef struct { FHalNfcChipConfig init; FHalNfcChipConfig deinit; + FHalNfcWaitEvent wait_event; FHalNfcChipConfig rx_start; - FHalNfcChipTx tx; - FHalNfcChipRx rx; + FHalNfcTx tx; + FHalNfcRx rx; } FHalNfcTechListenerBase; typedef struct { diff --git a/firmware/targets/f7/furi_hal/f_hal_nfc_iso14443a.c b/firmware/targets/f7/furi_hal/f_hal_nfc_iso14443a.c index aace2599d296..9579f35e7838 100644 --- a/firmware/targets/f7/furi_hal/f_hal_nfc_iso14443a.c +++ b/firmware/targets/f7/furi_hal/f_hal_nfc_iso14443a.c @@ -218,12 +218,16 @@ const FHalNfcTechBase f_hal_nfc_iso14443a = { { .init = f_hal_nfc_iso14443a_poller_init, .deinit = f_hal_nfc_iso14443a_poller_deinit, + .wait_event = f_hal_nfc_wait_event_common, + .tx = f_hal_nfc_poller_tx_common, + .rx = f_hal_nfc_common_fifo_rx, }, .listener = { .init = f_hal_nfc_iso14443a_listener_init, .deinit = f_hal_nfc_iso14443a_listener_deinit, + .wait_event = f_hal_nfc_wait_event_common, .rx_start = f_hal_nfc_common_listener_rx_start, .tx = f_hal_nfc_common_fifo_tx, .rx = f_hal_nfc_common_fifo_rx, diff --git a/firmware/targets/f7/furi_hal/f_hal_nfc_iso14443b.c b/firmware/targets/f7/furi_hal/f_hal_nfc_iso14443b.c index cf8be8eb5686..a66efbfa8144 100644 --- a/firmware/targets/f7/furi_hal/f_hal_nfc_iso14443b.c +++ b/firmware/targets/f7/furi_hal/f_hal_nfc_iso14443b.c @@ -93,6 +93,9 @@ const FHalNfcTechBase f_hal_nfc_iso14443b = { { .init = f_hal_nfc_iso14443b_poller_init, .deinit = f_hal_nfc_iso14443b_poller_deinit, + .wait_event = f_hal_nfc_wait_event_common, + .tx = f_hal_nfc_poller_tx_common, + .rx = f_hal_nfc_common_fifo_rx, }, .listener = {0}, diff --git a/firmware/targets/f7/furi_hal/f_hal_nfc_iso15693.c b/firmware/targets/f7/furi_hal/f_hal_nfc_iso15693.c index a4c528a72273..9cffba652cfb 100644 --- a/firmware/targets/f7/furi_hal/f_hal_nfc_iso15693.c +++ b/firmware/targets/f7/furi_hal/f_hal_nfc_iso15693.c @@ -1,47 +1,48 @@ #include "f_hal_nfc_i.h" -#include #include +#include #include -#define ISO15693_FC (13560000.0) -#define ISO15693_PULSE_DURATION_NS (128.0 * 1000000000.0 / ISO15693_FC) +#define F_HAL_NFC_ISO15693_MAX_FRAME_SIZE (1024U) +#define F_HAL_NFC_ISO15693_POLLER_MAX_BUFFER_SIZE (64) -#define FURI_HAL_ISO15693_BUFFER_SIZE (512U) +#define F_HAL_NFC_ISO15693_RESP_SOF_SIZE (5) +#define F_HAL_NFC_ISO15693_RESP_EOF_SIZE (5) +#define F_HAL_NFC_ISO15693_RESP_SOF_MASK (0x1FU) +#define F_HAL_NFC_ISO15693_RESP_SOF_PATTERN (0x17U) +#define F_HAL_NFC_ISO15693_RESP_EOF_PATTERN (0x1DU) + +#define F_HAL_NFC_ISO15693_RESP_PATTERN_MASK (0x03U) +#define F_HAL_NFC_ISO15693_RESP_PATTERN_0 (0x01U) +#define F_HAL_NFC_ISO15693_RESP_PATTERN_1 (0x02U) #define BITS_IN_BYTE (8U) #define TAG "FuriHalIso15693" -typedef enum { - FuriHalIso15693FrameStateSof1, - FuriHalIso15693FrameStateSof2, - FuriHalIso15693FrameStateCoding4, - FuriHalIso15693FrameStateCoding256, - FuriHalIso15693FrameStateEof, - FuriHalIso15693FrameStateReset, -} FuriHalIso15693FrameState; - typedef struct { - uint8_t rx_buf[FURI_HAL_ISO15693_BUFFER_SIZE]; - size_t rx_bytes; - uint32_t timestamp; - PulseReader* reader; Iso15693Signal* signal; + Iso15693Parser* parser; } FHalNfcIso15693Listener; -static FHalNfcIso15693Listener* f_hal_nfc_iso15693_listener; +typedef struct { + // 4 bits per data bit on transmit + uint8_t fifo_buf[F_HAL_NFC_ISO15693_POLLER_MAX_BUFFER_SIZE * 4]; + size_t fifo_buf_bits; + uint8_t frame_buf[F_HAL_NFC_ISO15693_POLLER_MAX_BUFFER_SIZE * 2]; + size_t frame_buf_bits; +} FHalNfcIso15693Poller; + +static FHalNfcIso15693Listener* f_hal_nfc_iso15693_listener = NULL; +static FHalNfcIso15693Poller* f_hal_nfc_iso15693_poller = NULL; static FHalNfcIso15693Listener* f_hal_nfc_iso15693_listener_alloc() { FHalNfcIso15693Listener* instance = malloc(sizeof(FHalNfcIso15693Listener)); - instance->reader = pulse_reader_alloc(&gpio_spi_r_miso, FURI_HAL_ISO15693_BUFFER_SIZE); - pulse_reader_set_timebase(instance->reader, PulseReaderUnitNanosecond); - pulse_reader_set_bittime(instance->reader, ISO15693_PULSE_DURATION_NS); - pulse_reader_set_pull(instance->reader, GpioPullDown); - instance->signal = iso15693_signal_alloc(&gpio_spi_r_mosi); + instance->parser = iso15693_parser_alloc(&gpio_spi_r_miso, F_HAL_NFC_ISO15693_MAX_FRAME_SIZE); return instance; } @@ -49,8 +50,20 @@ static FHalNfcIso15693Listener* f_hal_nfc_iso15693_listener_alloc() { static void f_hal_nfc_iso15693_listener_free(FHalNfcIso15693Listener* instance) { furi_assert(instance); - pulse_reader_free(instance->reader); iso15693_signal_free(instance->signal); + iso15693_parser_free(instance->parser); + + free(instance); +} + +static FHalNfcIso15693Poller* f_hal_nfc_iso15693_poller_alloc() { + FHalNfcIso15693Poller* instance = malloc(sizeof(FHalNfcIso15693Poller)); + + return instance; +} + +static void f_hal_nfc_iso15693_poller_free(FHalNfcIso15693Poller* instance) { + furi_assert(instance); free(instance); } @@ -94,6 +107,10 @@ static FHalNfcError f_hal_nfc_iso15693_common_init(FuriHalSpiBusHandle* handle) } static FHalNfcError f_hal_nfc_iso15693_poller_init(FuriHalSpiBusHandle* handle) { + furi_assert(f_hal_nfc_iso15693_poller == NULL); + + f_hal_nfc_iso15693_poller = f_hal_nfc_iso15693_poller_alloc(); + // Enable Subcarrier Stream mode, OOK modulation st25r3916_change_reg_bits( handle, @@ -120,9 +137,142 @@ static FHalNfcError f_hal_nfc_iso15693_poller_init(FuriHalSpiBusHandle* handle) static FHalNfcError f_hal_nfc_iso15693_poller_deinit(FuriHalSpiBusHandle* handle) { UNUSED(handle); + furi_assert(f_hal_nfc_iso15693_poller); + + f_hal_nfc_iso15693_poller_free(f_hal_nfc_iso15693_poller); + f_hal_nfc_iso15693_poller = NULL; + return FHalNfcErrorNone; } +static void iso15693_3_poller_encode_frame( + const uint8_t* tx_data, + size_t tx_bits, + uint8_t* frame_buf, + size_t frame_buf_size, + size_t* frame_buf_bits) { + static const uint8_t bit_patterns_1_out_of_4[] = {0x02, 0x08, 0x20, 0x80}; + size_t frame_buf_size_calc = (tx_bits / 2) + 2; + furi_assert(frame_buf_size >= frame_buf_size_calc); + + // Add SOF 1 out of 4 + frame_buf[0] = 0x21; + + size_t byte_pos = 1; + for(size_t i = 0; i < tx_bits / BITS_IN_BYTE; ++i) { + for(size_t j = 0; j < BITS_IN_BYTE; j += (BITS_IN_BYTE) / 4) { + const uint8_t bit_pair = (tx_data[i] >> j) & 0x03; + frame_buf[byte_pos++] = bit_patterns_1_out_of_4[bit_pair]; + } + } + // Add EOF + frame_buf[byte_pos++] = 0x04; + *frame_buf_bits = byte_pos * BITS_IN_BYTE; +} + +static bool iso15693_3_poller_decode_frame( + const uint8_t* buf, + size_t buf_bits, + uint8_t* buf_decoded, + size_t buf_decoded_size, + size_t* buf_decoded_bits) { + bool decoded = false; + size_t bit_pos = 0; + memset(buf_decoded, 0, buf_decoded_size); + + do { + if(buf_bits == 0) break; + // Check SOF + if((buf[0] & F_HAL_NFC_ISO15693_RESP_SOF_MASK) != F_HAL_NFC_ISO15693_RESP_SOF_PATTERN) + break; + + // 2 response bits = 1 data bit + for(uint32_t i = F_HAL_NFC_ISO15693_RESP_SOF_SIZE; + i < buf_bits - F_HAL_NFC_ISO15693_RESP_SOF_SIZE; + i += BITS_IN_BYTE / 4) { + const size_t byte_index = i / BITS_IN_BYTE; + const size_t bit_offset = i % BITS_IN_BYTE; + const uint8_t resp_byte = (buf[byte_index] >> bit_offset) | + (buf[byte_index + 1] << (BITS_IN_BYTE - bit_offset)); + + // Check EOF + if(resp_byte == F_HAL_NFC_ISO15693_RESP_EOF_PATTERN) { + decoded = true; + break; + } + + const uint8_t bit_pattern = resp_byte & F_HAL_NFC_ISO15693_RESP_PATTERN_MASK; + + if(bit_pattern == F_HAL_NFC_ISO15693_RESP_PATTERN_0) { + bit_pos++; + } else if(bit_pattern == F_HAL_NFC_ISO15693_RESP_PATTERN_1) { + buf_decoded[bit_pos / BITS_IN_BYTE] |= 1 << (bit_pos % BITS_IN_BYTE); + bit_pos++; + } else { + break; + } + if(bit_pos / BITS_IN_BYTE > buf_decoded_size) { + break; + } + } + + } while(false); + + if(decoded) { + *buf_decoded_bits = bit_pos; + } + + return decoded; +} + +static FHalNfcError f_hal_nfc_iso15693_poller_tx( + FuriHalSpiBusHandle* handle, + const uint8_t* tx_data, + size_t tx_bits) { + FHalNfcIso15693Poller* instance = f_hal_nfc_iso15693_poller; + iso15693_3_poller_encode_frame( + tx_data, + tx_bits, + instance->frame_buf, + sizeof(instance->frame_buf), + &instance->frame_buf_bits); + return f_hal_nfc_poller_tx_common(handle, instance->frame_buf, instance->frame_buf_bits); +} + +static FHalNfcError f_hal_nfc_iso15693_poller_rx( + FuriHalSpiBusHandle* handle, + uint8_t* rx_data, + size_t rx_data_size, + size_t* rx_bits) { + FHalNfcError error = FHalNfcErrorNone; + FHalNfcIso15693Poller* instance = f_hal_nfc_iso15693_poller; + + do { + error = f_hal_nfc_common_fifo_rx( + handle, instance->fifo_buf, sizeof(instance->fifo_buf), &instance->fifo_buf_bits); + if(error != FHalNfcErrorNone) break; + + if(!iso15693_3_poller_decode_frame( + instance->fifo_buf, + instance->fifo_buf_bits, + instance->frame_buf, + sizeof(instance->frame_buf), + &instance->frame_buf_bits)) { + error = FHalNfcErrorDataFormat; + break; + } + if(rx_data_size < instance->frame_buf_bits / BITS_IN_BYTE) { + error = FHalNfcErrorBufferOverflow; + break; + } + + memcpy(rx_data, instance->frame_buf, instance->frame_buf_bits / BITS_IN_BYTE); + *rx_bits = instance->frame_buf_bits; + } while(false); + + return error; +} + static FHalNfcError f_hal_nfc_iso15693_listener_init(FuriHalSpiBusHandle* handle) { furi_assert(f_hal_nfc_iso15693_listener == NULL); @@ -150,8 +300,10 @@ static FHalNfcError f_hal_nfc_iso15693_listener_init(FuriHalSpiBusHandle* handle static FHalNfcError f_hal_nfc_iso15693_listener_deinit(FuriHalSpiBusHandle* handle) { UNUSED(handle); + furi_assert(f_hal_nfc_iso15693_listener); f_hal_nfc_iso15693_listener_free(f_hal_nfc_iso15693_listener); + f_hal_nfc_iso15693_listener = NULL; return FHalNfcErrorNone; } @@ -161,8 +313,6 @@ static void f_hal_nfc_iso15693_listener_transparent_mode_enter(FuriHalSpiBusHand furi_hal_spi_bus_handle_deinit(handle); f_hal_nfc_deinit_gpio_isr(); - - furi_hal_gpio_init(&gpio_spi_r_miso, GpioModeInput, GpioPullNo, GpioSpeedVeryHigh); } static void f_hal_nfc_iso15693_listener_transparent_mode_exit(FuriHalSpiBusHandle* handle) { @@ -181,164 +331,52 @@ static FHalNfcError return FHalNfcErrorNone; } -static FHalNfcError f_hal_nfc_iso15693_listener_rx_transparent() { - uint32_t periods_previous = 0; - uint32_t frame_pos = 0; - uint32_t byte_value = 0; - uint32_t bits_received = 0; - bool wait_for_pulse = false; - - const uint32_t timeout = 1000000; +static FHalNfcError f_hal_nfc_iso15693_listener_rx_start(FuriHalSpiBusHandle* handle) { + UNUSED(handle); + return FHalNfcErrorNone; +} - FuriHalIso15693FrameState frame_state = FuriHalIso15693FrameStateSof1; - FHalNfcError ret = FHalNfcErrorNone; +static void f_hal_nfc_iso15693_parser_callback(Iso15693ParserEvent event, void* context) { + furi_assert(context); - pulse_reader_start(f_hal_nfc_iso15693_listener->reader); + if(event == Iso15693ParserEventDataReceived) { + FuriThreadId thread_id = context; + furi_thread_flags_set(thread_id, FHalNfcEventInternalTypeTransparentDataReceived); + } +} - for(;;) { - uint32_t periods = pulse_reader_receive(f_hal_nfc_iso15693_listener->reader, timeout); - const uint32_t timestamp = DWT->CYCCNT; +static FHalNfcEvent f_hal_nfc_iso15693_wait_event(uint32_t timeout_ms) { + FHalNfcEvent event = 0; + FuriHalSpiBusHandle* handle = &furi_hal_spi_bus_handle_nfc; - /* when timed out, reset to SOF state */ - if(periods == PULSE_READER_NO_EDGE || periods == PULSE_READER_LOST_EDGE) { - ret = FHalNfcErrorCommunicationTimeout; + f_hal_nfc_iso15693_listener_transparent_mode_enter(handle); + FuriThreadId thread_id = furi_thread_get_current_id(); + iso15693_parser_start( + f_hal_nfc_iso15693_listener->parser, f_hal_nfc_iso15693_parser_callback, thread_id); + + while(true) { + uint32_t flag = furi_thread_flags_wait( + FHalNfcEventInternalTypeAbort | FHalNfcEventInternalTypeTransparentDataReceived, + FuriFlagWaitAny, + timeout_ms); + furi_thread_flags_clear(flag); + + if(flag & FHalNfcEventInternalTypeAbort) { + event = FHalNfcEventAbortRequest; break; } - - /* short helper for detecting a pulse position */ - if(wait_for_pulse) { - wait_for_pulse = false; - if(periods != 1) { - frame_state = FuriHalIso15693FrameStateReset; - } - continue; - } - - switch(frame_state) { - case FuriHalIso15693FrameStateSof1: - frame_state = (periods == 1) ? FuriHalIso15693FrameStateSof2 : - FuriHalIso15693FrameStateSof1; - break; - - case FuriHalIso15693FrameStateSof2: - /* waiting for the second low period, telling us about coding */ - if(periods == 6) { - frame_state = FuriHalIso15693FrameStateCoding256; - periods_previous = 0; - wait_for_pulse = true; - } else if(periods == 4) { - frame_state = FuriHalIso15693FrameStateCoding4; - periods_previous = 2; - wait_for_pulse = true; - } else { - frame_state = FuriHalIso15693FrameStateReset; - } - break; - - case FuriHalIso15693FrameStateCoding256: - if(periods_previous > periods) { - frame_state = FuriHalIso15693FrameStateReset; - break; - } - - /* previous symbol left us with some pulse periods */ - periods -= periods_previous; - - if(periods > 512) { - frame_state = FuriHalIso15693FrameStateReset; - break; - } else if(periods == 2) { - frame_state = FuriHalIso15693FrameStateEof; - break; - } - - periods_previous = 512 - (periods + 1); - byte_value = (periods - 1) / 2; - if(frame_pos < FURI_HAL_ISO15693_BUFFER_SIZE) { - f_hal_nfc_iso15693_listener->rx_buf[frame_pos++] = (uint8_t)byte_value; - } - - wait_for_pulse = true; - break; - - case FuriHalIso15693FrameStateCoding4: - if(periods_previous > periods) { - frame_state = FuriHalIso15693FrameStateReset; - break; - } - - /* previous symbol left us with some pulse periods */ - periods -= periods_previous; - periods_previous = 0; - - byte_value >>= 2; - bits_received += 2; - - if(periods == 1) { - byte_value |= 0x00 << 6; // -V684 - periods_previous = 6; - } else if(periods == 3) { - byte_value |= 0x01 << 6; - periods_previous = 4; - } else if(periods == 5) { - byte_value |= 0x02 << 6; - periods_previous = 2; - } else if(periods == 7) { - byte_value |= 0x03 << 6; - periods_previous = 0; - } else if(periods == 2) { - frame_state = FuriHalIso15693FrameStateEof; + if(flag & FHalNfcEventInternalTypeTransparentDataReceived) { + if(iso15693_parser_run(f_hal_nfc_iso15693_listener->parser)) { + event = FHalNfcEventRxEnd; break; - } else { - frame_state = FuriHalIso15693FrameStateReset; - break; - } - - if(bits_received >= BITS_IN_BYTE) { - if(frame_pos < FURI_HAL_ISO15693_BUFFER_SIZE) { - f_hal_nfc_iso15693_listener->rx_buf[frame_pos++] = (uint8_t)byte_value; - } - bits_received = 0; } - wait_for_pulse = true; - break; - - default: - break; } - - if(frame_state == FuriHalIso15693FrameStateReset) { - frame_state = FuriHalIso15693FrameStateSof1; - } else if(frame_state == FuriHalIso15693FrameStateEof) { - f_hal_nfc_iso15693_listener->rx_bytes = frame_pos; - f_hal_nfc_iso15693_listener->timestamp = timestamp; - break; - } - } - - pulse_reader_stop(f_hal_nfc_iso15693_listener->reader); - - if(frame_state != FuriHalIso15693FrameStateEof) { - ret = FHalNfcErrorCommunication; } - return ret; -} - -static FHalNfcError f_hal_nfc_iso15693_listener_rx_start(FuriHalSpiBusHandle* handle) { - FHalNfcError error = FHalNfcErrorNone; - - f_hal_nfc_iso15693_listener_transparent_mode_enter(handle); - - error = f_hal_nfc_iso15693_listener_rx_transparent(); - + iso15693_parser_stop(f_hal_nfc_iso15693_listener->parser); f_hal_nfc_iso15693_listener_transparent_mode_exit(handle); - if(error == FHalNfcErrorNone) { - f_hal_nfc_event_set(FHalNfcEventInternalTypeTransparentRxEnd); - } - - return error; + return event; } static FHalNfcError f_hal_nfc_iso15693_listener_tx( @@ -365,18 +403,11 @@ static FHalNfcError f_hal_nfc_iso15693_listener_rx( furi_assert(f_hal_nfc_iso15693_listener); UNUSED(handle); - const size_t rx_bytes_ready = f_hal_nfc_iso15693_listener->rx_bytes; - const size_t rx_bits_ready = rx_bytes_ready * BITS_IN_BYTE; - - if(rx_bytes_ready > rx_data_size) { + if(rx_data_size < iso15693_parser_get_data_size_bytes(f_hal_nfc_iso15693_listener->parser)) { return FHalNfcErrorBufferOverflow; } - memcpy(rx_data, f_hal_nfc_iso15693_listener->rx_buf, rx_bytes_ready); - *rx_bits = rx_bits_ready; - - f_hal_nfc_iso15693_listener->rx_bytes = 0; - // f_hal_nfc_event_set(FHalNfcEventInternalTypeTransparentFieldOn); + iso15693_parser_get_data(f_hal_nfc_iso15693_listener->parser, rx_data, rx_data_size, rx_bits); return FHalNfcErrorNone; } @@ -386,12 +417,16 @@ const FHalNfcTechBase f_hal_nfc_iso15693 = { { .init = f_hal_nfc_iso15693_poller_init, .deinit = f_hal_nfc_iso15693_poller_deinit, + .wait_event = f_hal_nfc_wait_event_common, + .tx = f_hal_nfc_iso15693_poller_tx, + .rx = f_hal_nfc_iso15693_poller_rx, }, .listener = { .init = f_hal_nfc_iso15693_listener_init, .deinit = f_hal_nfc_iso15693_listener_deinit, + .wait_event = f_hal_nfc_iso15693_wait_event, .rx_start = f_hal_nfc_iso15693_listener_rx_start, .tx = f_hal_nfc_iso15693_listener_tx, .rx = f_hal_nfc_iso15693_listener_rx, diff --git a/firmware/targets/f7/target.json b/firmware/targets/f7/target.json index 0c083b68ddba..f58200c4688d 100644 --- a/firmware/targets/f7/target.json +++ b/firmware/targets/f7/target.json @@ -30,6 +30,7 @@ "nfc", "digital_signal", "pulse_reader", + "signal_reader", "microtar", "usb_stm32", "st25rfal002", diff --git a/firmware/targets/furi_hal_include/f_hal_nfc.h b/firmware/targets/furi_hal_include/f_hal_nfc.h index 2dd6177c31e3..ba8fb8eaaadd 100644 --- a/firmware/targets/furi_hal_include/f_hal_nfc.h +++ b/firmware/targets/furi_hal_include/f_hal_nfc.h @@ -38,6 +38,7 @@ typedef enum { FHalNfcErrorIsrTimeout, FHalNfcErrorCommunicationTimeout, FHalNfcErrorBufferOverflow, + FHalNfcErrorDataFormat, } FHalNfcError; typedef enum { @@ -105,6 +106,10 @@ FHalNfcError f_hal_nfc_acquire(); FHalNfcError f_hal_nfc_release(); +FHalNfcEvent f_hal_nfc_poller_wait_event(uint32_t timeout_ms); + +FHalNfcEvent f_hal_nfc_listener_wait_event(uint32_t timeout_ms); + FHalNfcError f_hal_nfc_poller_tx(const uint8_t* tx_data, size_t tx_bits); FHalNfcError f_hal_nfc_poller_tx_custom_parity(const uint8_t* tx_data, size_t tx_bits); @@ -131,8 +136,6 @@ FHalNfcError f_hal_nfc_abort(); FHalNfcError f_hal_nfc_event_start(); -FHalNfcEvent f_hal_nfc_event_wait(uint32_t timeout_ms); - void f_hal_nfc_timer_fwt_start(uint32_t time_fc); void f_hal_nfc_timer_fwt_stop(); diff --git a/lib/SConscript b/lib/SConscript index ab78c6ea4d44..9dfa35671a3b 100644 --- a/lib/SConscript +++ b/lib/SConscript @@ -5,6 +5,7 @@ env.Append( Dir("app-scened-template"), Dir("digital_signal"), Dir("pulse_reader"), + Dir("signal_reader"), Dir("drivers"), Dir("flipper_format"), Dir("infrared"), @@ -97,6 +98,7 @@ libs = env.BuildModules( "nfc", "digital_signal", "pulse_reader", + "signal_reader", "appframe", "misc", "lfrfid", diff --git a/lib/nfc/helpers/iso13239_crc.h b/lib/nfc/helpers/iso13239_crc.h index 7de2cd8a0f6c..c71ec6befe49 100644 --- a/lib/nfc/helpers/iso13239_crc.h +++ b/lib/nfc/helpers/iso13239_crc.h @@ -3,7 +3,7 @@ #include #include -#include "bit_buffer.h" +#include #ifdef __cplusplus extern "C" { diff --git a/lib/nfc/helpers/iso14443_crc.h b/lib/nfc/helpers/iso14443_crc.h index c9ad5397fc3e..14a63841e71f 100644 --- a/lib/nfc/helpers/iso14443_crc.h +++ b/lib/nfc/helpers/iso14443_crc.h @@ -3,7 +3,7 @@ #include #include -#include "bit_buffer.h" +#include #ifdef __cplusplus extern "C" { diff --git a/lib/nfc/nfc.c b/lib/nfc/nfc.c index 6d8881c5ba8d..8bdcfe070613 100644 --- a/lib/nfc/nfc.c +++ b/lib/nfc/nfc.c @@ -93,7 +93,7 @@ static int32_t nfc_worker_listener(void* context) { NfcCommand command = NfcCommandContinue; while(true) { - FHalNfcEvent event = f_hal_nfc_event_wait(F_HAL_NFC_EVENT_WAIT_FOREVER); + FHalNfcEvent event = f_hal_nfc_listener_wait_event(F_HAL_NFC_EVENT_WAIT_FOREVER); if(event & FHalNfcEventAbortRequest) { FURI_LOG_D(TAG, "Abort request received"); nfc_event.type = NfcEventTypeUserAbort; @@ -151,7 +151,7 @@ bool nfc_worker_poller_start_handler(Nfc* instance) { f_hal_nfc_poller_field_on(); if(instance->guard_time_us) { f_hal_nfc_timer_block_tx_start_us(instance->guard_time_us); - FHalNfcEvent event = f_hal_nfc_event_wait(F_HAL_NFC_EVENT_WAIT_FOREVER); + FHalNfcEvent event = f_hal_nfc_poller_wait_event(F_HAL_NFC_EVENT_WAIT_FOREVER); furi_assert(event & FHalNfcEventTimerBlockTxExpired); } instance->poller_state = NfcPollerStateReady; @@ -375,7 +375,7 @@ static NfcError nfc_poller_trx_state_machine(Nfc* instance, uint32_t fwt_fc) { NfcError error = NfcErrorNone; while(true) { - event = f_hal_nfc_event_wait(F_HAL_NFC_EVENT_WAIT_FOREVER); + event = f_hal_nfc_poller_wait_event(F_HAL_NFC_EVENT_WAIT_FOREVER); if(event & FHalNfcEventTimerBlockTxExpired) { if(instance->comm_state == NfcCommStateWaitBlockTxTimer) { instance->comm_state = NfcCommStateReadyTx; diff --git a/lib/nfc/nfc.h b/lib/nfc/nfc.h index f5a135e17e3e..ee140727c453 100644 --- a/lib/nfc/nfc.h +++ b/lib/nfc/nfc.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #ifdef __cplusplus extern "C" { diff --git a/lib/nfc/protocols/iso14443_3a/iso14443_3a.h b/lib/nfc/protocols/iso14443_3a/iso14443_3a.h index a899472f160e..ca7e4d9c0fcc 100644 --- a/lib/nfc/protocols/iso14443_3a/iso14443_3a.h +++ b/lib/nfc/protocols/iso14443_3a/iso14443_3a.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #ifdef __cplusplus diff --git a/lib/nfc/protocols/iso14443_3a/iso14443_3a_poller_i.h b/lib/nfc/protocols/iso14443_3a/iso14443_3a_poller_i.h index 99a2372bc96e..08483eb0009c 100644 --- a/lib/nfc/protocols/iso14443_3a/iso14443_3a_poller_i.h +++ b/lib/nfc/protocols/iso14443_3a/iso14443_3a_poller_i.h @@ -2,7 +2,7 @@ #include "iso14443_3a_poller.h" -#include +#include #ifdef __cplusplus extern "C" { diff --git a/lib/nfc/protocols/iso14443_3b/iso14443_3b.h b/lib/nfc/protocols/iso14443_3b/iso14443_3b.h index f222abd9db2e..b9b88788829a 100644 --- a/lib/nfc/protocols/iso14443_3b/iso14443_3b.h +++ b/lib/nfc/protocols/iso14443_3b/iso14443_3b.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #ifdef __cplusplus diff --git a/lib/nfc/protocols/iso14443_3b/iso14443_3b_poller_i.h b/lib/nfc/protocols/iso14443_3b/iso14443_3b_poller_i.h index 898378ac3604..ce42eb40ed35 100644 --- a/lib/nfc/protocols/iso14443_3b/iso14443_3b_poller_i.h +++ b/lib/nfc/protocols/iso14443_3b/iso14443_3b_poller_i.h @@ -2,8 +2,6 @@ #include "iso14443_3b_poller.h" -#include - #ifdef __cplusplus extern "C" { #endif diff --git a/lib/nfc/protocols/iso15693_3/iso15693_3_i.h b/lib/nfc/protocols/iso15693_3/iso15693_3_i.h index b747d413b182..01280e180822 100644 --- a/lib/nfc/protocols/iso15693_3/iso15693_3_i.h +++ b/lib/nfc/protocols/iso15693_3/iso15693_3_i.h @@ -2,7 +2,7 @@ #include "iso15693_3.h" -#include +#include #ifdef __cplusplus extern "C" { diff --git a/lib/nfc/protocols/iso15693_3/iso15693_3_poller.c b/lib/nfc/protocols/iso15693_3/iso15693_3_poller.c index ce4b084c72da..ffe27bc78459 100644 --- a/lib/nfc/protocols/iso15693_3/iso15693_3_poller.c +++ b/lib/nfc/protocols/iso15693_3/iso15693_3_poller.c @@ -20,10 +20,6 @@ static Iso15693_3Poller* iso15693_3_poller_alloc(Nfc* nfc) { instance->nfc = nfc; instance->tx_buffer = bit_buffer_alloc(ISO15693_3_POLLER_MAX_BUFFER_SIZE); instance->rx_buffer = bit_buffer_alloc(ISO15693_3_POLLER_MAX_BUFFER_SIZE); - // 4 bits per data bit on transmit - instance->tx_frame_buffer = bit_buffer_alloc(ISO15693_3_POLLER_MAX_BUFFER_SIZE * 4); - // 2 bits per data bit on receive - instance->rx_frame_buffer = bit_buffer_alloc(ISO15693_3_POLLER_MAX_BUFFER_SIZE * 2); nfc_config(instance->nfc, NfcModeIso15693Poller); nfc_set_guard_time_us(instance->nfc, ISO15693_3_GUARD_TIME_US); @@ -44,14 +40,10 @@ static void iso15693_3_poller_free(Iso15693_3Poller* instance) { furi_assert(instance->tx_buffer); furi_assert(instance->rx_buffer); - furi_assert(instance->tx_frame_buffer); - furi_assert(instance->rx_frame_buffer); furi_assert(instance->data); bit_buffer_free(instance->tx_buffer); bit_buffer_free(instance->rx_buffer); - bit_buffer_free(instance->tx_frame_buffer); - bit_buffer_free(instance->rx_frame_buffer); iso15693_3_free(instance->data); free(instance); } diff --git a/lib/nfc/protocols/iso15693_3/iso15693_3_poller_i.c b/lib/nfc/protocols/iso15693_3/iso15693_3_poller_i.c index 12aff5759918..23a053608c66 100644 --- a/lib/nfc/protocols/iso15693_3/iso15693_3_poller_i.c +++ b/lib/nfc/protocols/iso15693_3/iso15693_3_poller_i.c @@ -6,16 +6,6 @@ #define BITS_IN_BYTE (8) -#define ISO15693_RESP_SOF_SIZE (5) -#define ISO15693_RESP_EOF_SIZE (5) -#define ISO15693_RESP_SOF_MASK (0x1FU) -#define ISO15693_RESP_SOF_PATTERN (0x17U) -#define ISO15693_RESP_EOF_PATTERN (0x1DU) - -#define ISO15693_RESP_PATTERN_MASK (0x03U) -#define ISO15693_RESP_PATTERN_0 (0x01U) -#define ISO15693_RESP_PATTERN_1 (0x02U) - #define ISO15693_3_POLLER_NUM_BLOCKS_PER_QUERY (32U) static Iso15693_3Error iso15693_3_poller_process_nfc_error(NfcError error) { @@ -52,63 +42,6 @@ static Iso15693_3Error iso15693_3_poller_prepare_trx(Iso15693_3Poller* instance) return Iso15693_3ErrorNone; } -static void iso15693_3_poller_encode_byte(uint8_t data, BitBuffer* out) { - static const uint8_t bit_patterns_1_out_of_4[] = {0x02, 0x08, 0x20, 0x80}; - - for(uint32_t i = 0; i < BITS_IN_BYTE; i += (BITS_IN_BYTE) / 4) { - const uint8_t bit_pair = (data >> i) & 0x03; - bit_buffer_append_byte(out, bit_patterns_1_out_of_4[bit_pair]); - } -} - -static void iso15693_3_poller_encode_frame(const BitBuffer* data, BitBuffer* frame_data) { - bit_buffer_append_byte(frame_data, 0x21); // Add SOF 1 out of 4 - - for(size_t i = 0; i < bit_buffer_get_size_bytes(data); ++i) { - iso15693_3_poller_encode_byte(bit_buffer_get_byte(data, i), frame_data); - } - - bit_buffer_append_byte(frame_data, 0x04); // Add EOF -} - -static bool iso15693_3_poller_decode_frame(BitBuffer* data, const BitBuffer* frame_data) { - bool decoded = false; - - do { - if(bit_buffer_get_size(frame_data) == 0) break; - // Check SOF - if((bit_buffer_get_byte(frame_data, 0) & ISO15693_RESP_SOF_MASK) != - ISO15693_RESP_SOF_PATTERN) - break; - - // 2 response bits = 1 data bit - for(uint32_t i = ISO15693_RESP_SOF_SIZE; - i < bit_buffer_get_size(frame_data) - ISO15693_RESP_SOF_SIZE; - i += BITS_IN_BYTE / 4) { - const uint8_t resp_byte = bit_buffer_get_byte_from_bit(frame_data, i); - - // Check EOF - if(resp_byte == ISO15693_RESP_EOF_PATTERN) { - decoded = true; - break; - } - - const uint8_t bit_pattern = resp_byte & ISO15693_RESP_PATTERN_MASK; - - if(bit_pattern == ISO15693_RESP_PATTERN_0) { - bit_buffer_append_bit(data, false); - } else if(bit_pattern == ISO15693_RESP_PATTERN_1) { - bit_buffer_append_bit(data, true); - } else { - break; - } - } - - } while(false); - - return decoded; -} - static Iso15693_3Error iso15693_3_poller_frame_exchange( Iso15693_3Poller* instance, const BitBuffer* tx_buffer, @@ -128,23 +61,12 @@ static Iso15693_3Error iso15693_3_poller_frame_exchange( bit_buffer_copy(instance->tx_buffer, tx_buffer); iso13239_crc_append(Iso13239CrcTypeDefault, instance->tx_buffer); - bit_buffer_reset(instance->tx_frame_buffer); - bit_buffer_reset(instance->rx_frame_buffer); - - iso15693_3_poller_encode_frame(instance->tx_buffer, instance->tx_frame_buffer); - - NfcError error = - nfc_trx(instance->nfc, instance->tx_frame_buffer, instance->rx_frame_buffer, fwt); + NfcError error = nfc_trx(instance->nfc, instance->tx_buffer, instance->rx_buffer, fwt); if(error != NfcErrorNone) { ret = iso15693_3_poller_process_nfc_error(error); break; } - if(!iso15693_3_poller_decode_frame(instance->rx_buffer, instance->rx_frame_buffer)) { - ret = Iso15693_3ErrorFraming; - break; - } - if(!iso13239_crc_check(Iso13239CrcTypeDefault, instance->rx_buffer)) { ret = Iso15693_3ErrorWrongCrc; break; diff --git a/lib/nfc/protocols/iso15693_3/iso15693_3_poller_i.h b/lib/nfc/protocols/iso15693_3/iso15693_3_poller_i.h index 6b6073132a20..154ee684c97c 100644 --- a/lib/nfc/protocols/iso15693_3/iso15693_3_poller_i.h +++ b/lib/nfc/protocols/iso15693_3/iso15693_3_poller_i.h @@ -4,7 +4,7 @@ #include "iso15693_3_i.h" -#include +#include #ifdef __cplusplus extern "C" { @@ -25,8 +25,6 @@ struct Iso15693_3Poller { Iso15693_3Data* data; BitBuffer* tx_buffer; BitBuffer* rx_buffer; - BitBuffer* tx_frame_buffer; - BitBuffer* rx_frame_buffer; NfcGenericEvent general_event; Iso15693_3PollerEvent iso15693_3_event; diff --git a/lib/nfc/protocols/mf_classic/crypto1.h b/lib/nfc/protocols/mf_classic/crypto1.h index 4273ac82c5b5..f2bdb272b0e6 100644 --- a/lib/nfc/protocols/mf_classic/crypto1.h +++ b/lib/nfc/protocols/mf_classic/crypto1.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #ifdef __cplusplus extern "C" { diff --git a/lib/signal_reader/SConscript b/lib/signal_reader/SConscript new file mode 100644 index 000000000000..ea7314420189 --- /dev/null +++ b/lib/signal_reader/SConscript @@ -0,0 +1,20 @@ +Import("env") + +env.Append( + CPPPATH=[ + "#/lib/signal_reader", + ], + SDK_HEADERS=[ + File("signal_reader.h"), + ], +) + +libenv = env.Clone(FW_LIB_NAME="signal_reader") +libenv.ApplyLibFlags() +libenv.Append(CCFLAGS=["-O3", "-funroll-loops", "-Ofast"]) + +sources = libenv.GlobRecursive("*.c*") + +lib = libenv.StaticLibrary("${FW_LIB_NAME}", sources) +libenv.Install("${LIB_DIST_DIR}", lib) +Return("lib") diff --git a/lib/signal_reader/parsers/iso15693/iso15693_parser.c b/lib/signal_reader/parsers/iso15693/iso15693_parser.c new file mode 100644 index 000000000000..80652e57b08c --- /dev/null +++ b/lib/signal_reader/parsers/iso15693/iso15693_parser.c @@ -0,0 +1,334 @@ +#include "iso15693_parser.h" + +#include + +#include + +#define ISO15693_PARSER_BITSTREAM_BUFF_SIZE (8) +#define ISO15693_PARSER_BITRATE_F64MHZ (603U) + +#define TAG "Iso15693Parser" + +typedef enum { + Iso15693ParserStateParseSoF, + Iso15693ParserStateParse1OutOf4, + Iso15693ParserStateParse1OutOf256, + + Iso15693ParserStateNum, +} Iso15693ParserState; + +struct Iso15693Parser { + Iso15693ParserState state; + + SignalReader* signal_reader; + + uint8_t bitstream_buff[ISO15693_PARSER_BITSTREAM_BUFF_SIZE]; + size_t bitstream_idx; + uint8_t last_byte; + + bool signal_detected; + bool bit_offset_calculated; + uint8_t bit_offset; + size_t byte_idx; + size_t bytes_to_process; + + uint8_t next_byte; + uint16_t next_byte_part; + bool zero_found; + + BitBuffer* parsed_frame; + bool frame_parsed; + + Iso15693ParserCallback callback; + void* context; +}; + +typedef enum { + Iso15693ParserCommandProcessed, + Iso15693ParserCommandWaitData, + Iso15693ParserCommandFail, + Iso15693ParserCommandSuccess, +} Iso15693ParserCommand; + +typedef Iso15693ParserCommand (*Iso15693ParserStateHandler)(Iso15693Parser* instance); + +Iso15693Parser* iso15693_parser_alloc(const GpioPin* pin, size_t max_frame_size) { + Iso15693Parser* instance = malloc(sizeof(Iso15693Parser)); + instance->parsed_frame = bit_buffer_alloc(max_frame_size); + + instance->signal_reader = signal_reader_alloc(pin, ISO15693_PARSER_BITSTREAM_BUFF_SIZE); + signal_reader_set_sample_rate( + instance->signal_reader, SignalReaderTimeUnit64Mhz, ISO15693_PARSER_BITRATE_F64MHZ); + signal_reader_set_pull(instance->signal_reader, GpioPullDown); + signal_reader_set_polarity(instance->signal_reader, SignalReaderPolarityInverted); + + return instance; +} + +void iso15693_parser_free(Iso15693Parser* instance) { + furi_assert(instance); + + bit_buffer_free(instance->parsed_frame); + signal_reader_free(instance->signal_reader); + free(instance); +} + +void iso15693_parser_reset(Iso15693Parser* instance) { + furi_assert(instance); + + instance->state = Iso15693ParserStateParseSoF; + memset(instance->bitstream_buff, 0x00, sizeof(instance->bitstream_buff)); + instance->bitstream_idx = 0; + + instance->next_byte = 0; + instance->next_byte_part = 0; + + instance->bit_offset = 0; + instance->byte_idx = 0; + instance->bytes_to_process = 0; + instance->signal_detected = false; + instance->bit_offset_calculated = false; + + instance->last_byte = 0x00; + instance->zero_found = false; + + bit_buffer_reset(instance->parsed_frame); + instance->frame_parsed = false; +} + +static void signal_reader_callback(SignalReaderEvent event, void* context) { + furi_assert(context); + furi_assert(event.data->data); + furi_assert(event.data->len == ISO15693_PARSER_BITSTREAM_BUFF_SIZE / 2); + + Iso15693Parser* instance = context; + furi_assert(instance->callback); + + if(!instance->signal_detected) { + size_t i = 0; + for(i = 0; i < event.data->len; i++) { + if(event.data->data[i] != 0x00) { + break; + } + } + if(i != event.data->len) { + memcpy(instance->bitstream_buff, &event.data->data[i], event.data->len - i); + instance->bytes_to_process = event.data->len - i; + instance->signal_detected = true; + } + } else { + memcpy( + &instance->bitstream_buff[instance->bytes_to_process], + event.data->data, + event.data->len); + instance->bytes_to_process += event.data->len; + } + if(instance->bytes_to_process >= ISO15693_PARSER_BITSTREAM_BUFF_SIZE / 4) { + instance->callback(Iso15693ParserEventDataReceived, instance->context); + } +} + +static void iso15693_parser_start_signal_reader(Iso15693Parser* instance) { + iso15693_parser_reset(instance); + signal_reader_start(instance->signal_reader, signal_reader_callback, instance); +} + +void iso15693_parser_start( + Iso15693Parser* instance, + Iso15693ParserCallback callback, + void* context) { + furi_assert(instance); + furi_assert(callback); + + instance->callback = callback; + instance->context = context; + iso15693_parser_start_signal_reader(instance); +} + +void iso15693_parser_stop(Iso15693Parser* instance) { + furi_assert(instance); + + signal_reader_stop(instance->signal_reader); +} +static void iso15693_parser_prepare_buff(Iso15693Parser* instance) { + if(!instance->bit_offset_calculated) { + for(size_t i = 0; i < 8; i++) { + if(FURI_BIT(instance->bitstream_buff[0], i)) { + instance->bit_offset = i; + break; + } + } + if(instance->bit_offset == 7) { + if(FURI_BIT(instance->bitstream_buff[1], 0) == 1) { + instance->bit_offset = 0; + for(size_t i = 0; i < instance->bytes_to_process - 1; i++) { + instance->bitstream_buff[i] = instance->bitstream_buff[i + 1]; + instance->bytes_to_process--; + } + } + } else { + if(FURI_BIT(instance->bitstream_buff[0], instance->bit_offset + 1) == 1) { + instance->bit_offset++; + } + } + + for(size_t i = 0; i < instance->bytes_to_process - 1; i++) { + instance->bitstream_buff[i] = + (instance->bitstream_buff[i] >> instance->bit_offset) | + (instance->bitstream_buff[i + 1] << (8 - instance->bit_offset)); + } + instance->last_byte = instance->bitstream_buff[instance->bytes_to_process - 1]; + instance->bytes_to_process--; + instance->bit_offset_calculated = true; + } else { + for(size_t i = 0; i < instance->bytes_to_process; i++) { + uint8_t next_byte = instance->bitstream_buff[i]; + instance->bitstream_buff[i] = (instance->last_byte >> instance->bit_offset) | + (next_byte << (8 - instance->bit_offset)); + instance->last_byte = next_byte; + } + } +} + +static Iso15693ParserCommand iso15693_parser_parse_sof(Iso15693Parser* instance) { + Iso15693ParserCommand command = Iso15693ParserCommandProcessed; + const uint8_t sof_1_out_of_4 = 0x21; + const uint8_t sof_1_out_of_256 = 0x81; + const uint8_t eof = 0x01; + + if(instance->bitstream_buff[0] == sof_1_out_of_4) { + instance->state = Iso15693ParserStateParse1OutOf4; + instance->byte_idx = 1; + } else if(instance->bitstream_buff[0] == sof_1_out_of_256) { + instance->state = Iso15693ParserStateParse1OutOf256; + instance->byte_idx = 1; + } else if(instance->bitstream_buff[0] == eof) { + instance->frame_parsed = true; + command = Iso15693ParserCommandSuccess; + } else { + command = Iso15693ParserCommandFail; + } + + return command; +} + +static Iso15693ParserCommand iso15693_parser_parse_1_out_of_4(Iso15693Parser* instance) { + Iso15693ParserCommand command = Iso15693ParserCommandWaitData; + const uint8_t bit_patterns_1_out_of_4[] = {0x02, 0x08, 0x20, 0x80}; + const uint8_t eof = 0x04; + + for(size_t i = instance->byte_idx; i < instance->bytes_to_process; i++) { + // Check EoF + if(instance->next_byte_part == 0) { + if(instance->bitstream_buff[i] == eof) { + instance->frame_parsed = true; + command = Iso15693ParserCommandSuccess; + break; + } + } + + // Check next pattern + size_t j = 0; + for(j = 0; j < COUNT_OF(bit_patterns_1_out_of_4); j++) { + if(instance->bitstream_buff[i] == bit_patterns_1_out_of_4[j]) { + instance->next_byte |= j << (instance->next_byte_part * 2); + instance->next_byte_part++; + if(instance->next_byte_part == 4) { + instance->next_byte_part = 0; + bit_buffer_append_byte(instance->parsed_frame, instance->next_byte); + instance->next_byte = 0; + } + break; + } + } + if(j == COUNT_OF(bit_patterns_1_out_of_4)) { + command = Iso15693ParserCommandFail; + break; + } + } + instance->bytes_to_process = 0; + instance->byte_idx = 0; + + return command; +} + +static Iso15693ParserCommand iso15693_parser_parse_1_out_of_256(Iso15693Parser* instance) { + Iso15693ParserCommand command = Iso15693ParserCommandWaitData; + const uint8_t eof = 0x04; + + for(size_t i = instance->byte_idx; i < instance->bytes_to_process; i++) { + // Check EoF + if(instance->next_byte_part == 0) { + if(instance->bitstream_buff[i] == eof) { + instance->frame_parsed = true; + command = Iso15693ParserCommandSuccess; + break; + } + } + + if(instance->zero_found) { + if(instance->bitstream_buff[i] != 0x00) { + command = Iso15693ParserCommandFail; + break; + } + } else { + if(instance->bitstream_buff[i] != 0x00) { + for(size_t j = 0; j < 8; j++) { + if(FURI_BIT(instance->bitstream_buff[i], j) == 1) { + bit_buffer_append_byte( + instance->parsed_frame, instance->next_byte_part * 4 + j / 2); + } + } + } + } + instance->next_byte_part = (instance->next_byte_part + 1) % 64; + } + instance->bytes_to_process = 0; + instance->byte_idx = 0; + + return command; +} + +static const Iso15693ParserStateHandler iso15693_parser_state_handlers[Iso15693ParserStateNum] = { + [Iso15693ParserStateParseSoF] = iso15693_parser_parse_sof, + [Iso15693ParserStateParse1OutOf4] = iso15693_parser_parse_1_out_of_4, + [Iso15693ParserStateParse1OutOf256] = iso15693_parser_parse_1_out_of_256, +}; + +bool iso15693_parser_run(Iso15693Parser* instance) { + if(instance->bytes_to_process) { + iso15693_parser_prepare_buff(instance); + + Iso15693ParserCommand command = Iso15693ParserCommandProcessed; + while(command == Iso15693ParserCommandProcessed) { + command = iso15693_parser_state_handlers[instance->state](instance); + } + + if(command == Iso15693ParserCommandFail) { + FURI_LOG_D(TAG, "Frame parse failed"); + iso15693_parser_stop(instance); + iso15693_parser_start_signal_reader(instance); + } + } + + return instance->frame_parsed; +} + +size_t iso15693_parser_get_data_size_bytes(Iso15693Parser* instance) { + furi_assert(instance); + + return bit_buffer_get_size_bytes(instance->parsed_frame); +} + +void iso15693_parser_get_data( + Iso15693Parser* instance, + uint8_t* buff, + size_t buff_size, + size_t* data_bits) { + furi_assert(instance); + furi_assert(buff); + furi_assert(data_bits); + + bit_buffer_write_bytes(instance->parsed_frame, buff, buff_size); + *data_bits = bit_buffer_get_size(instance->parsed_frame); +} diff --git a/lib/signal_reader/parsers/iso15693/iso15693_parser.h b/lib/signal_reader/parsers/iso15693/iso15693_parser.h new file mode 100644 index 000000000000..3017a96d79ac --- /dev/null +++ b/lib/signal_reader/parsers/iso15693/iso15693_parser.h @@ -0,0 +1,42 @@ +#pragma once + +#include "../../signal_reader.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct Iso15693Parser Iso15693Parser; + +typedef enum { + Iso15693ParserEventDataReceived, +} Iso15693ParserEvent; + +typedef void (*Iso15693ParserCallback)(Iso15693ParserEvent event, void* context); + +Iso15693Parser* iso15693_parser_alloc(const GpioPin* pin, size_t max_frame_size); + +void iso15693_parser_free(Iso15693Parser* instance); + +void iso15693_parser_reset(Iso15693Parser* instance); + +void iso15693_parser_start( + Iso15693Parser* instance, + Iso15693ParserCallback callback, + void* context); + +void iso15693_parser_stop(Iso15693Parser* instance); + +bool iso15693_parser_run(Iso15693Parser* instance); + +size_t iso15693_parser_get_data_size_bytes(Iso15693Parser* instance); + +void iso15693_parser_get_data( + Iso15693Parser* instance, + uint8_t* buff, + size_t buff_size, + size_t* data_bits); + +#ifdef __cplusplus +} +#endif diff --git a/lib/signal_reader/signal_reader.c b/lib/signal_reader/signal_reader.c new file mode 100644 index 000000000000..b6758eebd605 --- /dev/null +++ b/lib/signal_reader/signal_reader.c @@ -0,0 +1,289 @@ +#include "signal_reader.h" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#define SIGNAL_READER_DMA DMA2 + +#define SIGNAL_READER_CAPTURE_TIM (TIM16) +#define SIGNAL_READER_CAPTURE_TIM_CHANNEL LL_TIM_CHANNEL_CH1 + +#define SIGNAL_READER_DMA_GPIO LL_DMA_CHANNEL_2 +#define SIGNAL_READER_DMA_GPIO_IRQ FuriHalInterruptIdDma2Ch2 +#define SIGNAL_READER_DMA_GPIO_DEF SIGNAL_READER_DMA, SIGNAL_READER_DMA_GPIO + +#define SIGNAL_READER_DMA_CNT_SYNC LL_DMA_CHANNEL_5 +#define SIGNAL_READER_DMA_CNT_SYNC_IRQ FuriHalInterruptIdDma2Ch5 +#define SIGNAL_READER_DMA_CNT_SYNC_DEF SIGNAL_READER_DMA, SIGNAL_READER_DMA_CNT_SYNC + +struct SignalReader { + size_t buffer_size; + const GpioPin* pin; + GpioPull pull; + SignalReaderPolarity polarity; + uint16_t* gpio_buffer; + uint8_t* bitstream_buffer; + + uint32_t tim_cnt_compensation; + uint32_t tim_arr; + + SignalReaderEvent event; + SignalReaderEventData event_data; + + SignalReaderCallback callback; + void* context; +}; + +#define GPIO_PIN_MAP(pin, prefix) \ + (((pin) == (LL_GPIO_PIN_0)) ? prefix##0 : \ + ((pin) == (LL_GPIO_PIN_1)) ? prefix##1 : \ + ((pin) == (LL_GPIO_PIN_2)) ? prefix##2 : \ + ((pin) == (LL_GPIO_PIN_3)) ? prefix##3 : \ + ((pin) == (LL_GPIO_PIN_4)) ? prefix##4 : \ + ((pin) == (LL_GPIO_PIN_5)) ? prefix##5 : \ + ((pin) == (LL_GPIO_PIN_6)) ? prefix##6 : \ + ((pin) == (LL_GPIO_PIN_7)) ? prefix##7 : \ + ((pin) == (LL_GPIO_PIN_8)) ? prefix##8 : \ + ((pin) == (LL_GPIO_PIN_9)) ? prefix##9 : \ + ((pin) == (LL_GPIO_PIN_10)) ? prefix##10 : \ + ((pin) == (LL_GPIO_PIN_11)) ? prefix##11 : \ + ((pin) == (LL_GPIO_PIN_12)) ? prefix##12 : \ + ((pin) == (LL_GPIO_PIN_13)) ? prefix##13 : \ + ((pin) == (LL_GPIO_PIN_14)) ? prefix##14 : \ + prefix##15) + +#define GET_DMAMUX_EXTI_LINE(pin) GPIO_PIN_MAP(pin, LL_DMAMUX_REQ_GEN_EXTI_LINE) + +SignalReader* signal_reader_alloc(const GpioPin* gpio_pin, uint32_t size) { + SignalReader* instance = malloc(sizeof(SignalReader)); + + instance->pin = gpio_pin; + instance->pull = GpioPullNo; + + instance->buffer_size = size; + instance->gpio_buffer = malloc(sizeof(uint16_t) * size * 8); + instance->bitstream_buffer = malloc(size); + + instance->event.data = &instance->event_data; + + return instance; +} + +void signal_reader_free(SignalReader* instance) { + furi_assert(instance); + furi_assert(instance->gpio_buffer); + furi_assert(instance->bitstream_buffer); + + free(instance->gpio_buffer); + free(instance->bitstream_buffer); + free(instance); +} + +void signal_reader_set_pull(SignalReader* instance, GpioPull pull) { + furi_assert(instance); + + instance->pull = pull; +} + +void signal_reader_set_polarity(SignalReader* instance, SignalReaderPolarity polarity) { + furi_assert(instance); + + instance->polarity = polarity; +} + +void signal_reader_set_sample_rate( + SignalReader* instance, + SignalReaderTimeUnit time_unit, + uint32_t time) { + furi_assert(instance); + UNUSED(time_unit); + + instance->tim_arr = time; +} + +static void furi_hal_sw_digital_pin_dma_rx_isr(void* context) { + SignalReader* instance = context; + + uint16_t* gpio_buff_start = NULL; + uint8_t* bitstream_buff_start = NULL; + + if(LL_DMA_IsActiveFlag_HT2(SIGNAL_READER_DMA)) { + LL_DMA_ClearFlag_HT2(SIGNAL_READER_DMA); + instance->event.type = SignalReaderEventTypeHalfBufferFilled; + gpio_buff_start = instance->gpio_buffer; + bitstream_buff_start = instance->bitstream_buffer; + + if(instance->callback) { + furi_assert(gpio_buff_start); + furi_assert(bitstream_buff_start); + + for(size_t i = 0; i < instance->buffer_size * 4; i++) { + if((i % 8) == 0) { + bitstream_buff_start[i / 8] = 0; + } + uint8_t bit = 0; + if(instance->polarity == SignalReaderPolarityNormal) { + bit = (gpio_buff_start[i] & instance->pin->pin) == instance->pin->pin; + } else { + bit = (gpio_buff_start[i] & instance->pin->pin) == 0; + } + bitstream_buff_start[i / 8] |= bit << (i % 8); + } + instance->event_data.data = bitstream_buff_start; + instance->event_data.len = instance->buffer_size / 2; + instance->callback(instance->event, instance->context); + } + } + if(LL_DMA_IsActiveFlag_TC2(SIGNAL_READER_DMA)) { + LL_DMA_ClearFlag_TC2(SIGNAL_READER_DMA); + instance->event.type = SignalReaderEventTypeFullBufferFilled; + gpio_buff_start = &instance->gpio_buffer[instance->buffer_size * 4]; + bitstream_buff_start = &instance->bitstream_buffer[instance->buffer_size / 2]; + + if(instance->callback) { + furi_assert(gpio_buff_start); + furi_assert(bitstream_buff_start); + + for(size_t i = 0; i < instance->buffer_size * 4; i++) { + if((i % 8) == 0) { + bitstream_buff_start[i / 8] = 0; + } + uint8_t bit = 0; + if(instance->polarity == SignalReaderPolarityNormal) { + bit = (gpio_buff_start[i] & instance->pin->pin) == instance->pin->pin; + } else { + bit = (gpio_buff_start[i] & instance->pin->pin) == 0; + } + bitstream_buff_start[i / 8] |= bit << (i % 8); + } + instance->event_data.data = bitstream_buff_start; + instance->event_data.len = instance->buffer_size / 2; + instance->callback(instance->event, instance->context); + } + } +} + +void signal_reader_start(SignalReader* instance, SignalReaderCallback callback, void* context) { + furi_assert(instance); + furi_assert(callback); + + instance->callback = callback; + instance->context = context; + + // EXTI delay compensation + instance->tim_cnt_compensation = 9; + + furi_hal_bus_enable(FuriHalBusTIM16); + + // Capture timer config + LL_TIM_SetPrescaler(SIGNAL_READER_CAPTURE_TIM, 0); + LL_TIM_SetCounterMode(SIGNAL_READER_CAPTURE_TIM, LL_TIM_COUNTERMODE_UP); + LL_TIM_SetAutoReload(SIGNAL_READER_CAPTURE_TIM, instance->tim_arr); + LL_TIM_SetClockDivision(SIGNAL_READER_CAPTURE_TIM, LL_TIM_CLOCKDIVISION_DIV1); + + LL_TIM_DisableARRPreload(SIGNAL_READER_CAPTURE_TIM); + LL_TIM_SetClockSource(SIGNAL_READER_CAPTURE_TIM, LL_TIM_CLOCKSOURCE_INTERNAL); + + // Configure TIM channel CC1 + LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {}; + TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_FROZEN; + TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_DISABLE; + TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_DISABLE; + TIM_OC_InitStruct.CompareValue = (instance->tim_arr / 2); + TIM_OC_InitStruct.OCPolarity = LL_TIM_OCPOLARITY_HIGH; + LL_TIM_OC_Init( + SIGNAL_READER_CAPTURE_TIM, SIGNAL_READER_CAPTURE_TIM_CHANNEL, &TIM_OC_InitStruct); + LL_TIM_OC_DisableFast(SIGNAL_READER_CAPTURE_TIM, SIGNAL_READER_CAPTURE_TIM_CHANNEL); + + LL_TIM_SetTriggerOutput(SIGNAL_READER_CAPTURE_TIM, LL_TIM_TRGO_RESET); + LL_TIM_DisableMasterSlaveMode(SIGNAL_READER_CAPTURE_TIM); + + // Start + LL_TIM_GenerateEvent_UPDATE(SIGNAL_READER_CAPTURE_TIM); + + /* We need the EXTI to be configured as interrupt generating line, but no ISR registered */ + furi_hal_gpio_init( + instance->pin, GpioModeInterruptRiseFall, instance->pull, GpioSpeedVeryHigh); + furi_delay_ms(10); + + /* Set DMAMUX request generation signal ID on specified DMAMUX channel */ + LL_DMAMUX_SetRequestSignalID( + DMAMUX1, LL_DMAMUX_REQ_GEN_0, GET_DMAMUX_EXTI_LINE(instance->pin->pin)); + /* Set the polarity of the signal on which the DMA request is generated */ + LL_DMAMUX_SetRequestGenPolarity(DMAMUX1, LL_DMAMUX_REQ_GEN_0, LL_DMAMUX_REQ_GEN_POL_RISING); + /* Set the number of DMA requests that will be authorized after a generation event */ + LL_DMAMUX_SetGenRequestNb(DMAMUX1, LL_DMAMUX_REQ_GEN_0, 1); + + // Configure DMA Sync + LL_DMA_SetMemoryAddress( + SIGNAL_READER_DMA_CNT_SYNC_DEF, (uint32_t)&instance->tim_cnt_compensation); + LL_DMA_SetPeriphAddress( + SIGNAL_READER_DMA_CNT_SYNC_DEF, (uint32_t) & (SIGNAL_READER_CAPTURE_TIM->CNT)); + LL_DMA_ConfigTransfer( + SIGNAL_READER_DMA_CNT_SYNC_DEF, + LL_DMA_DIRECTION_MEMORY_TO_PERIPH | LL_DMA_MODE_CIRCULAR | LL_DMA_PERIPH_NOINCREMENT | + LL_DMA_MEMORY_NOINCREMENT | LL_DMA_PDATAALIGN_HALFWORD | LL_DMA_MDATAALIGN_HALFWORD | + LL_DMA_PRIORITY_VERYHIGH); + LL_DMA_SetDataLength(SIGNAL_READER_DMA_CNT_SYNC_DEF, 1); + LL_DMA_SetPeriphRequest(SIGNAL_READER_DMA_CNT_SYNC_DEF, LL_DMAMUX_REQ_GENERATOR0); + + // Configure DMA Rx pin + LL_DMA_SetMemoryAddress(SIGNAL_READER_DMA_GPIO_DEF, (uint32_t)instance->gpio_buffer); + LL_DMA_SetPeriphAddress(SIGNAL_READER_DMA_GPIO_DEF, (uint32_t) & (instance->pin->port->IDR)); + LL_DMA_ConfigTransfer( + SIGNAL_READER_DMA_GPIO_DEF, + LL_DMA_DIRECTION_PERIPH_TO_MEMORY | LL_DMA_MODE_CIRCULAR | LL_DMA_PERIPH_NOINCREMENT | + LL_DMA_MEMORY_INCREMENT | LL_DMA_PDATAALIGN_HALFWORD | LL_DMA_MDATAALIGN_HALFWORD | + LL_DMA_PRIORITY_HIGH); + LL_DMA_SetDataLength(SIGNAL_READER_DMA_GPIO_DEF, instance->buffer_size * 8); + LL_DMA_SetPeriphRequest(SIGNAL_READER_DMA_GPIO_DEF, LL_DMAMUX_REQ_TIM16_CH1); + + // Configure DMA Channel CC1 + LL_TIM_EnableDMAReq_CC1(SIGNAL_READER_CAPTURE_TIM); + LL_TIM_CC_EnableChannel(SIGNAL_READER_CAPTURE_TIM, SIGNAL_READER_CAPTURE_TIM_CHANNEL); + + // Start DMA irq, higher priority than normal + furi_hal_interrupt_set_isr_ex( + SIGNAL_READER_DMA_GPIO_IRQ, 14, furi_hal_sw_digital_pin_dma_rx_isr, instance); + + // Start DMA Sync timer + LL_DMA_EnableChannel(SIGNAL_READER_DMA_CNT_SYNC_DEF); + LL_DMAMUX_EnableRequestGen(DMAMUX1, LL_DMAMUX_REQ_GEN_0); + + // Start DMA Rx pin + LL_DMA_EnableChannel(SIGNAL_READER_DMA_GPIO_DEF); + // Strat timer + LL_TIM_SetCounter(SIGNAL_READER_CAPTURE_TIM, 0); + LL_TIM_EnableCounter(SIGNAL_READER_CAPTURE_TIM); + + // Need to clear flags before enabling DMA !!!! + if(LL_DMA_IsActiveFlag_TC2(SIGNAL_READER_DMA)) LL_DMA_ClearFlag_TC1(SIGNAL_READER_DMA); + if(LL_DMA_IsActiveFlag_TE2(SIGNAL_READER_DMA)) LL_DMA_ClearFlag_TE1(SIGNAL_READER_DMA); + LL_DMA_EnableIT_TC(SIGNAL_READER_DMA_GPIO_DEF); + LL_DMA_EnableIT_HT(SIGNAL_READER_DMA_GPIO_DEF); +} + +void signal_reader_stop(SignalReader* instance) { + furi_assert(instance); + + furi_hal_interrupt_set_isr(SIGNAL_READER_DMA_GPIO_IRQ, NULL, NULL); + + // Deinit DMA Rx pin + LL_DMA_DeInit(SIGNAL_READER_DMA_GPIO_DEF); + // Deinit DMA Sync timer + LL_DMA_DeInit(SIGNAL_READER_DMA_CNT_SYNC_DEF); + + furi_hal_bus_disable(FuriHalBusTIM16); + + memset(instance->gpio_buffer, 0, sizeof(uint16_t) * instance->buffer_size * 8); + memset(instance->bitstream_buffer, 0, instance->buffer_size); +} diff --git a/lib/signal_reader/signal_reader.h b/lib/signal_reader/signal_reader.h new file mode 100644 index 000000000000..2213465c37c2 --- /dev/null +++ b/lib/signal_reader/signal_reader.h @@ -0,0 +1,60 @@ +#pragma once + +#include +#include +#include + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + SignalReaderEventTypeHalfBufferFilled, + SignalReaderEventTypeFullBufferFilled, +} SignalReaderEventType; + +typedef struct { + uint8_t* data; + size_t len; +} SignalReaderEventData; + +typedef struct { + SignalReaderEventType type; + SignalReaderEventData* data; +} SignalReaderEvent; + +typedef enum { + SignalReaderTimeUnit64Mhz, +} SignalReaderTimeUnit; + +typedef enum { + SignalReaderPolarityNormal, + SignalReaderPolarityInverted, +} SignalReaderPolarity; + +typedef void (*SignalReaderCallback)(SignalReaderEvent event, void* context); + +typedef struct SignalReader SignalReader; + +SignalReader* signal_reader_alloc(const GpioPin* gpio_pin, uint32_t size); + +void signal_reader_free(SignalReader* instance); + +void signal_reader_set_pull(SignalReader* instance, GpioPull pull); + +void signal_reader_set_polarity(SignalReader* instance, SignalReaderPolarity polarity); + +void signal_reader_set_sample_rate( + SignalReader* instance, + SignalReaderTimeUnit time_unit, + uint32_t time); + +void signal_reader_start(SignalReader* instance, SignalReaderCallback callback, void* context); + +void signal_reader_stop(SignalReader* instance); + +#ifdef __cplusplus +} +#endif diff --git a/lib/nfc/helpers/bit_buffer.c b/lib/toolbox/bit_buffer.c similarity index 100% rename from lib/nfc/helpers/bit_buffer.c rename to lib/toolbox/bit_buffer.c diff --git a/lib/nfc/helpers/bit_buffer.h b/lib/toolbox/bit_buffer.h similarity index 100% rename from lib/nfc/helpers/bit_buffer.h rename to lib/toolbox/bit_buffer.h