diff --git a/applications/main/nfc/application.fam b/applications/main/nfc/application.fam index 27b11d8da06f..25a232056ce0 100644 --- a/applications/main/nfc/application.fam +++ b/applications/main/nfc/application.fam @@ -9,7 +9,7 @@ App( "gui", "dialogs", ], - # provides=["nfc_start"], + provides=["nfc_start"], icon="A_NFC_14", stack_size=5 * 1024, order=30, @@ -52,10 +52,10 @@ App( requires=["nfc"], ) -# App( -# appid="nfc_start", -# apptype=FlipperAppType.STARTUP, -# entry_point="nfc_on_system_start", -# requires=["nfc"], -# order=30, -# ) +App( + appid="nfc_start", + apptype=FlipperAppType.STARTUP, + entry_point="nfc_on_system_start", + requires=["nfc"], + order=30, +) diff --git a/applications/main/nfc/nfc_cli.c b/applications/main/nfc/nfc_cli.c index 320cd94bf7dd..818a27ec18de 100644 --- a/applications/main/nfc/nfc_cli.c +++ b/applications/main/nfc/nfc_cli.c @@ -4,8 +4,15 @@ #include #include -#include -#include +#include +#include +#include +#include + +#include +#include + +#define FLAG_EVENT (1 << 10) static void nfc_cli_print_usage() { printf("Usage:\r\n"); @@ -19,155 +26,72 @@ static void nfc_cli_print_usage() { } } -static void nfc_cli_check(Cli* cli, FuriString* args) { - UNUSED(args); - UNUSED(cli); -} +static void f_hal_nfc_iso15693_listener_transparent_mode_enter(FuriHalSpiBusHandle* handle) { + st25r3916_direct_cmd(handle, ST25R3916_CMD_TRANSPARENT_MODE); -static void nfc_cli_detect(Cli* cli, FuriString* args) { - UNUSED(args); - // Check if nfc worker is not busy - if(furi_hal_nfc_is_busy()) { - printf("Nfc is busy\r\n"); - return; - } - - FuriHalNfcDevData dev_data = {}; - bool cmd_exit = false; - furi_hal_nfc_exit_sleep(); - printf("Detecting nfc...\r\nPress Ctrl+C to abort\r\n"); - while(!cmd_exit) { - cmd_exit |= cli_cmd_interrupt_received(cli); - if(furi_hal_nfc_detect(&dev_data, 400)) { - printf("Found: %s ", nfc_get_dev_type(dev_data.type)); - printf("UID length: %d, UID:", dev_data.uid_len); - for(size_t i = 0; i < dev_data.uid_len; i++) { - printf("%02X", dev_data.uid[i]); - } - printf("\r\n"); - break; - } - furi_hal_nfc_sleep(); - furi_delay_ms(50); - } - furi_hal_nfc_sleep(); + furi_hal_spi_bus_handle_deinit(handle); + f_hal_nfc_deinit_gpio_isr(); } -static void nfc_cli_emulate(Cli* cli, FuriString* args) { - UNUSED(args); - // Check if nfc worker is not busy - if(furi_hal_nfc_is_busy()) { - printf("Nfc is busy\r\n"); - return; - } +static void f_hal_nfc_iso15693_listener_transparent_mode_exit(FuriHalSpiBusHandle* handle) { + // Configure gpio back to SPI and exit transparent mode + f_hal_nfc_init_gpio_isr(); + furi_hal_spi_bus_handle_init(handle); - furi_hal_nfc_exit_sleep(); - printf("Emulating NFC-A Type: T2T UID: 36 9C E7 B1 0A C1 34 SAK: 00 ATQA: 00/44\r\n"); - printf("Press Ctrl+C to abort\r\n"); - - FuriHalNfcDevData params = { - .uid = {0x36, 0x9C, 0xe7, 0xb1, 0x0A, 0xC1, 0x34}, - .uid_len = 7, - .atqa = {0x44, 0x00}, - .sak = 0x00, - .type = FuriHalNfcTypeA, - }; - - while(!cli_cmd_interrupt_received(cli)) { - if(furi_hal_nfc_listen(params.uid, params.uid_len, params.atqa, params.sak, false, 100)) { - printf("Reader detected\r\n"); - furi_hal_nfc_sleep(); - } - furi_delay_ms(50); - } - furi_hal_nfc_sleep(); + st25r3916_direct_cmd(handle, ST25R3916_CMD_UNMASK_RECEIVE_DATA); } -static void nfc_cli_field(Cli* cli, FuriString* args) { - UNUSED(args); - // Check if nfc worker is not busy - if(furi_hal_nfc_is_busy()) { - printf("Nfc is busy\r\n"); - return; - } - - furi_hal_nfc_exit_sleep(); - furi_hal_nfc_field_on(); - - printf("Field is on. Don't leave device in this mode for too long.\r\n"); - printf("Press Ctrl+C to abort\r\n"); +static void f_hal_nfc_iso15693_parser_callback(Iso15693ParserEvent event, void* context) { + furi_assert(context); - while(!cli_cmd_interrupt_received(cli)) { - furi_delay_ms(50); + if(event == Iso15693ParserEventDataReceived) { + FuriThreadId thread_id = context; + furi_thread_flags_set(thread_id, FLAG_EVENT); } - - furi_hal_nfc_field_off(); - furi_hal_nfc_sleep(); } -static void nfc_cli_apdu(Cli* cli, FuriString* args) { +// TODO remove this test command +static void nfc_cli_check(Cli* cli, FuriString* args) { + UNUSED(args); UNUSED(cli); - if(furi_hal_nfc_is_busy()) { - printf("Nfc is busy\r\n"); - return; + FuriHalSpiBusHandle* handle = &furi_hal_spi_bus_handle_nfc; + uint8_t data[100] = {}; + size_t bits = 0; + + Nfc* nfc = nfc_alloc(); + f_hal_nfc_low_power_mode_stop(); + f_hal_nfc_set_mode(FHalNfcModeListener, FHalNfcTechIso15693); + f_hal_nfc_iso15693_listener_transparent_mode_enter(handle); + Iso15693Parser* instance = iso15693_parser_alloc(&gpio_spi_r_miso, 1024); + + FuriThreadId thread_id = furi_thread_get_current_id(); + furi_thread_set_current_priority(FuriThreadPriorityHighest); + iso15693_parser_start(instance, f_hal_nfc_iso15693_parser_callback, thread_id); + + while(true) { + uint32_t flag = furi_thread_flags_wait(FLAG_EVENT, FuriFlagWaitAny, FuriWaitForever); + furi_thread_flags_clear(flag); + + if(flag & FLAG_EVENT) { + if(iso15693_parser_run(instance)) { + iso15693_parser_get_data(instance, data, sizeof(data), &bits); + break; + } + } } - furi_hal_nfc_exit_sleep(); - FuriString* data = NULL; - data = furi_string_alloc(); - FuriHalNfcTxRxContext tx_rx = {}; - FuriHalNfcDevData dev_data = {}; - uint8_t* req_buffer = NULL; - uint8_t* resp_buffer = NULL; - size_t apdu_size = 0; - size_t resp_size = 0; + for(size_t i = 0; i < bits / 8; i++) { + printf("%02X ", data[i]); + } + printf("\r\n"); - do { - if(!args_read_string_and_trim(args, data)) { - printf( - "Use like `nfc apdu 00a404000e325041592e5359532e444446303100 00a4040008a0000003010102` \r\n"); - break; - } + iso15693_parser_stop(instance); + f_hal_nfc_iso15693_listener_transparent_mode_exit(handle); - printf("detecting tag\r\n"); - if(!furi_hal_nfc_detect(&dev_data, 300)) { - printf("Failed to detect tag\r\n"); - break; - } - do { - apdu_size = furi_string_size(data) / 2; - req_buffer = malloc(apdu_size); - hex_chars_to_uint8(furi_string_get_cstr(data), req_buffer); - - memcpy(tx_rx.tx_data, req_buffer, apdu_size); - tx_rx.tx_bits = apdu_size * 8; - tx_rx.tx_rx_type = FuriHalNfcTxRxTypeDefault; - - printf("Sending APDU:%s to Tag\r\n", furi_string_get_cstr(data)); - if(!furi_hal_nfc_tx_rx(&tx_rx, 300)) { - printf("Failed to tx_rx\r\n"); - break; - } - resp_size = (tx_rx.rx_bits / 8) * 2; - if(!resp_size) { - printf("No response\r\n"); - break; - } - resp_buffer = malloc(resp_size); - uint8_to_hex_chars(tx_rx.rx_data, resp_buffer, resp_size); - resp_buffer[resp_size] = 0; - printf("Response: %s\r\n", resp_buffer); - free(req_buffer); - free(resp_buffer); - req_buffer = NULL; - resp_buffer = NULL; - } while(args_read_string_and_trim(args, data)); - } while(false); - - free(req_buffer); - free(resp_buffer); - furi_string_free(data); - furi_hal_nfc_sleep(); + iso15693_parser_free(instance); + f_hal_nfc_reset_mode(); + f_hal_nfc_low_power_mode_start(); + nfc_free(nfc); } static void nfc_cli(Cli* cli, FuriString* args, void* context) { @@ -184,26 +108,6 @@ static void nfc_cli(Cli* cli, FuriString* args, void* context) { nfc_cli_check(cli, args); break; } - if(furi_string_cmp_str(cmd, "detect") == 0) { - nfc_cli_detect(cli, args); - break; - } - if(furi_string_cmp_str(cmd, "emulate") == 0) { - nfc_cli_emulate(cli, args); - break; - } - - if(furi_string_cmp_str(cmd, "apdu") == 0) { - nfc_cli_apdu(cli, args); - break; - } - - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - if(furi_string_cmp_str(cmd, "field") == 0) { - nfc_cli_field(cli, args); - break; - } - } nfc_cli_print_usage(); } while(false); diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 1948b85e5e5b..95e8eab74318 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,+,36.1,, +Version,+,35.3,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -2677,6 +2677,7 @@ 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_set_trigger,void,"SignalReader*, SignalReaderTrigger" Function,+,signal_reader_start,void,"SignalReader*, SignalReaderCallback, void*" Function,+,signal_reader_stop,void,SignalReader* Function,+,simple_array_alloc,SimpleArray*,const SimpleArrayConfig* 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 9cffba652cfb..fbaaa08985d7 100644 --- a/firmware/targets/f7/furi_hal/f_hal_nfc_iso15693.c +++ b/firmware/targets/f7/furi_hal/f_hal_nfc_iso15693.c @@ -363,6 +363,7 @@ static FHalNfcEvent f_hal_nfc_iso15693_wait_event(uint32_t timeout_ms) { if(flag & FHalNfcEventInternalTypeAbort) { event = FHalNfcEventAbortRequest; + f_hal_nfc_iso15693_listener_transparent_mode_exit(handle); break; } if(flag & FHalNfcEventInternalTypeTransparentDataReceived) { @@ -372,9 +373,7 @@ static FHalNfcEvent f_hal_nfc_iso15693_wait_event(uint32_t timeout_ms) { } } } - iso15693_parser_stop(f_hal_nfc_iso15693_listener->parser); - f_hal_nfc_iso15693_listener_transparent_mode_exit(handle); return event; } @@ -386,7 +385,6 @@ static FHalNfcError f_hal_nfc_iso15693_listener_tx( furi_assert(f_hal_nfc_iso15693_listener); FHalNfcError error = FHalNfcErrorNone; - f_hal_nfc_iso15693_listener_transparent_mode_enter(handle); error = f_hal_nfc_iso15693_listener_tx_transparent(tx_data, tx_bits / BITS_IN_BYTE); diff --git a/lib/signal_reader/parsers/iso15693/iso15693_parser.c b/lib/signal_reader/parsers/iso15693/iso15693_parser.c index 80652e57b08c..6fbe91a4c22d 100644 --- a/lib/signal_reader/parsers/iso15693/iso15693_parser.c +++ b/lib/signal_reader/parsers/iso15693/iso15693_parser.c @@ -4,21 +4,27 @@ #include -#define ISO15693_PARSER_BITSTREAM_BUFF_SIZE (8) +#define ISO15693_PARSER_SIGNAL_READER_BUFF_SIZE (2) +#define ISO15693_PARSER_BITSTREAM_BUFF_SIZE (32) #define ISO15693_PARSER_BITRATE_F64MHZ (603U) #define TAG "Iso15693Parser" typedef enum { Iso15693ParserStateParseSoF, - Iso15693ParserStateParse1OutOf4, - Iso15693ParserStateParse1OutOf256, - - Iso15693ParserStateNum, + Iso15693ParserStateParseFrame, } Iso15693ParserState; +typedef enum { + Iso15693ParserMode1OutOf4, + Iso15693ParserMode1OutOf256, + + Iso15693ParserModeNum, +} Iso15693ParserMode; + struct Iso15693Parser { Iso15693ParserState state; + Iso15693ParserMode mode; SignalReader* signal_reader; @@ -37,6 +43,7 @@ struct Iso15693Parser { bool zero_found; BitBuffer* parsed_frame; + bool eof_received; bool frame_parsed; Iso15693ParserCallback callback; @@ -56,11 +63,12 @@ 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); + instance->signal_reader = signal_reader_alloc(pin, ISO15693_PARSER_SIGNAL_READER_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); + signal_reader_set_trigger(instance->signal_reader, SignalReaderTriggerRisingFallingEdge); return instance; } @@ -77,6 +85,7 @@ void iso15693_parser_reset(Iso15693Parser* instance) { furi_assert(instance); instance->state = Iso15693ParserStateParseSoF; + instance->mode = Iso15693ParserMode1OutOf4; memset(instance->bitstream_buff, 0x00, sizeof(instance->bitstream_buff)); instance->bitstream_idx = 0; @@ -91,6 +100,7 @@ void iso15693_parser_reset(Iso15693Parser* instance) { instance->last_byte = 0x00; instance->zero_found = false; + instance->eof_received = false; bit_buffer_reset(instance->parsed_frame); instance->frame_parsed = false; @@ -99,32 +109,46 @@ void iso15693_parser_reset(Iso15693Parser* instance) { 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); + furi_assert(event.data->len == ISO15693_PARSER_SIGNAL_READER_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; + const uint8_t sof_1_out_of_4 = 0x21; + const uint8_t sof_1_out_of_256 = 0x81; + const uint8_t eof_single = 0x01; + const uint8_t eof = 0x04; + + if(instance->state == Iso15693ParserStateParseSoF) { + if(event.data->data[0] == sof_1_out_of_4) { + instance->mode = Iso15693ParserMode1OutOf4; + instance->state = Iso15693ParserStateParseFrame; + } else if(event.data->data[0] == sof_1_out_of_256) { + instance->mode = Iso15693ParserMode1OutOf256; + instance->state = Iso15693ParserStateParseFrame; + } else if(event.data->data[0] == eof_single) { + instance->eof_received = true; + instance->callback(Iso15693ParserEventDataReceived, instance->context); } } 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); + if(instance->mode == Iso15693ParserMode1OutOf4) { + if(event.data->data[0] == eof) { + instance->eof_received = true; + instance->callback(Iso15693ParserEventDataReceived, instance->context); + } else { + instance->bitstream_buff[instance->bytes_to_process] = event.data->data[0]; + instance->bytes_to_process++; + if(instance->bytes_to_process == ISO15693_PARSER_BITSTREAM_BUFF_SIZE) { + instance->callback(Iso15693ParserEventDataReceived, instance->context); + } + } + } else { + instance->bitstream_buff[instance->bytes_to_process] = event.data->data[0]; + instance->bytes_to_process++; + if(instance->bytes_to_process == ISO15693_PARSER_BITSTREAM_BUFF_SIZE) { + instance->callback(Iso15693ParserEventDataReceived, instance->context); + } + } } } @@ -150,83 +174,12 @@ void iso15693_parser_stop(Iso15693Parser* 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; - } - } + for(size_t i = 0; i < instance->bytes_to_process; i++) { // Check next pattern size_t j = 0; for(j = 0; j < COUNT_OF(bit_patterns_1_out_of_4); j++) { @@ -246,8 +199,15 @@ static Iso15693ParserCommand iso15693_parser_parse_1_out_of_4(Iso15693Parser* in break; } } + + if(command != Iso15693ParserCommandFail) { + if(instance->eof_received) { + command = Iso15693ParserCommandSuccess; + instance->frame_parsed = true; + } + } + instance->bytes_to_process = 0; - instance->byte_idx = 0; return command; } @@ -289,19 +249,18 @@ static Iso15693ParserCommand iso15693_parser_parse_1_out_of_256(Iso15693Parser* 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, +static const Iso15693ParserStateHandler iso15693_parser_state_handlers[Iso15693ParserModeNum] = { + [Iso15693ParserMode1OutOf4] = iso15693_parser_parse_1_out_of_4, + [Iso15693ParserMode1OutOf256] = iso15693_parser_parse_1_out_of_256, }; bool iso15693_parser_run(Iso15693Parser* instance) { - if(instance->bytes_to_process) { - iso15693_parser_prepare_buff(instance); - + if((instance->state == Iso15693ParserStateParseSoF) && (instance->eof_received)) { + instance->frame_parsed = true; + } else if(instance->bytes_to_process) { Iso15693ParserCommand command = Iso15693ParserCommandProcessed; while(command == Iso15693ParserCommandProcessed) { - command = iso15693_parser_state_handlers[instance->state](instance); + command = iso15693_parser_state_handlers[instance->mode](instance); } if(command == Iso15693ParserCommandFail) { diff --git a/lib/signal_reader/signal_reader.c b/lib/signal_reader/signal_reader.c index b6758eebd605..43f6486c4808 100644 --- a/lib/signal_reader/signal_reader.c +++ b/lib/signal_reader/signal_reader.c @@ -21,6 +21,10 @@ #define SIGNAL_READER_DMA_GPIO_IRQ FuriHalInterruptIdDma2Ch2 #define SIGNAL_READER_DMA_GPIO_DEF SIGNAL_READER_DMA, SIGNAL_READER_DMA_GPIO +#define SIGNAL_READER_DMA_TRIGGER LL_DMA_CHANNEL_3 +#define SIGNAL_READER_DMA_TRIGGER_IRQ FuriHalInterruptIdDma2Ch3 +#define SIGNAL_READER_DMA_TRIGGER_DEF SIGNAL_READER_DMA, SIGNAL_READER_DMA_TRIGGER + #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 @@ -30,8 +34,11 @@ struct SignalReader { const GpioPin* pin; GpioPull pull; SignalReaderPolarity polarity; + SignalReaderTrigger trigger; + uint16_t* gpio_buffer; uint8_t* bitstream_buffer; + uint32_t cnt_en; uint32_t tim_cnt_compensation; uint32_t tim_arr; @@ -110,6 +117,12 @@ void signal_reader_set_sample_rate( instance->tim_arr = time; } +void signal_reader_set_trigger(SignalReader* instance, SignalReaderTrigger trigger) { + furi_assert(instance); + + instance->trigger = trigger; +} + static void furi_hal_sw_digital_pin_dma_rx_isr(void* context) { SignalReader* instance = context; @@ -181,6 +194,8 @@ void signal_reader_start(SignalReader* instance, SignalReaderCallback callback, // EXTI delay compensation instance->tim_cnt_compensation = 9; + instance->cnt_en = SIGNAL_READER_CAPTURE_TIM->CR1; + instance->cnt_en |= TIM_CR1_CEN; furi_hal_bus_enable(FuriHalBusTIM16); @@ -236,6 +251,17 @@ void signal_reader_start(SignalReader* instance, SignalReaderCallback callback, 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 Sync + LL_DMA_SetMemoryAddress(SIGNAL_READER_DMA_TRIGGER_DEF, (uint32_t)&instance->cnt_en); + LL_DMA_SetPeriphAddress( + SIGNAL_READER_DMA_TRIGGER_DEF, (uint32_t) & (SIGNAL_READER_CAPTURE_TIM->CR1)); + LL_DMA_ConfigTransfer( + SIGNAL_READER_DMA_TRIGGER_DEF, + LL_DMA_DIRECTION_MEMORY_TO_PERIPH | 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_TRIGGER_DEF, 1); + LL_DMA_SetPeriphRequest(SIGNAL_READER_DMA_TRIGGER_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)); @@ -257,14 +283,18 @@ void signal_reader_start(SignalReader* instance, SignalReaderCallback callback, // 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); + if(instance->trigger == SignalReaderTriggerNone) { + LL_TIM_EnableCounter(SIGNAL_READER_CAPTURE_TIM); + } else { + LL_DMA_EnableChannel(SIGNAL_READER_DMA_TRIGGER_DEF); + } + LL_DMAMUX_EnableRequestGen(DMAMUX1, LL_DMAMUX_REQ_GEN_0); // 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); @@ -281,9 +311,8 @@ void signal_reader_stop(SignalReader* instance) { LL_DMA_DeInit(SIGNAL_READER_DMA_GPIO_DEF); // Deinit DMA Sync timer LL_DMA_DeInit(SIGNAL_READER_DMA_CNT_SYNC_DEF); + // Deinit DMA Trigger timer + LL_DMA_DeInit(SIGNAL_READER_DMA_TRIGGER_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 index 2213465c37c2..be18f295a448 100644 --- a/lib/signal_reader/signal_reader.h +++ b/lib/signal_reader/signal_reader.h @@ -34,6 +34,11 @@ typedef enum { SignalReaderPolarityInverted, } SignalReaderPolarity; +typedef enum { + SignalReaderTriggerNone, + SignalReaderTriggerRisingFallingEdge, +} SignalReaderTrigger; + typedef void (*SignalReaderCallback)(SignalReaderEvent event, void* context); typedef struct SignalReader SignalReader; @@ -51,6 +56,8 @@ void signal_reader_set_sample_rate( SignalReaderTimeUnit time_unit, uint32_t time); +void signal_reader_set_trigger(SignalReader* instance, SignalReaderTrigger trigger); + void signal_reader_start(SignalReader* instance, SignalReaderCallback callback, void* context); void signal_reader_stop(SignalReader* instance);