diff --git a/applications/external/nfc_rfid_detector/application.fam b/applications/external/nfc_rfid_detector/application.fam new file mode 100644 index 00000000..70c91bc8 --- /dev/null +++ b/applications/external/nfc_rfid_detector/application.fam @@ -0,0 +1,13 @@ +App( + appid="nfc_rfid_detector", + name="NFC/RFID detector", + apptype=FlipperAppType.EXTERNAL, + targets=["f7"], + entry_point="nfc_rfid_detector_app", + requires=["gui"], + stack_size=4 * 1024, + order=50, + fap_icon="nfc_rfid_detector_10px.png", + fap_category="Tools", + fap_icon_assets="images", +) diff --git a/applications/external/nfc_rfid_detector/helpers/nfc_rfid_detector_event.h b/applications/external/nfc_rfid_detector/helpers/nfc_rfid_detector_event.h new file mode 100644 index 00000000..bbffe293 --- /dev/null +++ b/applications/external/nfc_rfid_detector/helpers/nfc_rfid_detector_event.h @@ -0,0 +1,7 @@ +#pragma once + +typedef enum { + //NfcRfidDetectorCustomEvent + NfcRfidDetectorCustomEventStartId = 100, + +} NfcRfidDetectorCustomEvent; diff --git a/applications/external/nfc_rfid_detector/helpers/nfc_rfid_detector_types.h b/applications/external/nfc_rfid_detector/helpers/nfc_rfid_detector_types.h new file mode 100644 index 00000000..5d44b09b --- /dev/null +++ b/applications/external/nfc_rfid_detector/helpers/nfc_rfid_detector_types.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include + +#define NFC_RFID_DETECTOR_VERSION_APP "0.1" +#define NFC_RFID_DETECTOR_DEVELOPED "SkorP" +#define NFC_RFID_DETECTOR_GITHUB "https://github.com/flipperdevices/flipperzero-firmware" + +typedef enum { + NfcRfidDetectorViewVariableItemList, + NfcRfidDetectorViewSubmenu, + NfcRfidDetectorViewFieldPresence, + NfcRfidDetectorViewWidget, +} NfcRfidDetectorView; diff --git a/applications/external/nfc_rfid_detector/images/Modern_reader_18x34.png b/applications/external/nfc_rfid_detector/images/Modern_reader_18x34.png new file mode 100644 index 00000000..b19c0f30 Binary files /dev/null and b/applications/external/nfc_rfid_detector/images/Modern_reader_18x34.png differ diff --git a/applications/external/nfc_rfid_detector/images/Move_flipper_26x39.png b/applications/external/nfc_rfid_detector/images/Move_flipper_26x39.png new file mode 100644 index 00000000..ff4af9ff Binary files /dev/null and b/applications/external/nfc_rfid_detector/images/Move_flipper_26x39.png differ diff --git a/applications/external/nfc_rfid_detector/images/NFC_detect_45x30.png b/applications/external/nfc_rfid_detector/images/NFC_detect_45x30.png new file mode 100644 index 00000000..9d8a6f2a Binary files /dev/null and b/applications/external/nfc_rfid_detector/images/NFC_detect_45x30.png differ diff --git a/applications/external/nfc_rfid_detector/images/Rfid_detect_45x30.png b/applications/external/nfc_rfid_detector/images/Rfid_detect_45x30.png new file mode 100644 index 00000000..35c20504 Binary files /dev/null and b/applications/external/nfc_rfid_detector/images/Rfid_detect_45x30.png differ diff --git a/applications/external/nfc_rfid_detector/nfc_rfid_detector_10px.png b/applications/external/nfc_rfid_detector/nfc_rfid_detector_10px.png new file mode 100644 index 00000000..7e875e02 Binary files /dev/null and b/applications/external/nfc_rfid_detector/nfc_rfid_detector_10px.png differ diff --git a/applications/external/nfc_rfid_detector/nfc_rfid_detector_app.c b/applications/external/nfc_rfid_detector/nfc_rfid_detector_app.c new file mode 100644 index 00000000..cba8b608 --- /dev/null +++ b/applications/external/nfc_rfid_detector/nfc_rfid_detector_app.c @@ -0,0 +1,108 @@ +#include "nfc_rfid_detector_app_i.h" + +#include +#include + +static bool nfc_rfid_detector_app_custom_event_callback(void* context, uint32_t event) { + furi_assert(context); + NfcRfidDetectorApp* app = context; + return scene_manager_handle_custom_event(app->scene_manager, event); +} + +static bool nfc_rfid_detector_app_back_event_callback(void* context) { + furi_assert(context); + NfcRfidDetectorApp* app = context; + return scene_manager_handle_back_event(app->scene_manager); +} + +static void nfc_rfid_detector_app_tick_event_callback(void* context) { + furi_assert(context); + NfcRfidDetectorApp* app = context; + scene_manager_handle_tick_event(app->scene_manager); +} + +NfcRfidDetectorApp* nfc_rfid_detector_app_alloc() { + NfcRfidDetectorApp* app = malloc(sizeof(NfcRfidDetectorApp)); + + // GUI + app->gui = furi_record_open(RECORD_GUI); + + // View Dispatcher + app->view_dispatcher = view_dispatcher_alloc(); + app->scene_manager = scene_manager_alloc(&nfc_rfid_detector_scene_handlers, app); + view_dispatcher_enable_queue(app->view_dispatcher); + + view_dispatcher_set_event_callback_context(app->view_dispatcher, app); + view_dispatcher_set_custom_event_callback( + app->view_dispatcher, nfc_rfid_detector_app_custom_event_callback); + view_dispatcher_set_navigation_event_callback( + app->view_dispatcher, nfc_rfid_detector_app_back_event_callback); + view_dispatcher_set_tick_event_callback( + app->view_dispatcher, nfc_rfid_detector_app_tick_event_callback, 100); + + view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen); + + // Open Notification record + app->notifications = furi_record_open(RECORD_NOTIFICATION); + + // SubMenu + app->submenu = submenu_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, NfcRfidDetectorViewSubmenu, submenu_get_view(app->submenu)); + + // Widget + app->widget = widget_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, NfcRfidDetectorViewWidget, widget_get_view(app->widget)); + + // Field Presence + app->nfc_rfid_detector_field_presence = nfc_rfid_detector_view_field_presence_alloc(); + view_dispatcher_add_view( + app->view_dispatcher, + NfcRfidDetectorViewFieldPresence, + nfc_rfid_detector_view_field_presence_get_view(app->nfc_rfid_detector_field_presence)); + + scene_manager_next_scene(app->scene_manager, NfcRfidDetectorSceneStart); + + return app; +} + +void nfc_rfid_detector_app_free(NfcRfidDetectorApp* app) { + furi_assert(app); + + // Submenu + view_dispatcher_remove_view(app->view_dispatcher, NfcRfidDetectorViewSubmenu); + submenu_free(app->submenu); + + // Widget + view_dispatcher_remove_view(app->view_dispatcher, NfcRfidDetectorViewWidget); + widget_free(app->widget); + + // Field Presence + view_dispatcher_remove_view(app->view_dispatcher, NfcRfidDetectorViewFieldPresence); + nfc_rfid_detector_view_field_presence_free(app->nfc_rfid_detector_field_presence); + + // View dispatcher + view_dispatcher_free(app->view_dispatcher); + scene_manager_free(app->scene_manager); + + // Notifications + furi_record_close(RECORD_NOTIFICATION); + app->notifications = NULL; + + // Close records + furi_record_close(RECORD_GUI); + + free(app); +} + +int32_t nfc_rfid_detector_app(void* p) { + UNUSED(p); + NfcRfidDetectorApp* nfc_rfid_detector_app = nfc_rfid_detector_app_alloc(); + + view_dispatcher_run(nfc_rfid_detector_app->view_dispatcher); + + nfc_rfid_detector_app_free(nfc_rfid_detector_app); + + return 0; +} diff --git a/applications/external/nfc_rfid_detector/nfc_rfid_detector_app_i.c b/applications/external/nfc_rfid_detector/nfc_rfid_detector_app_i.c new file mode 100644 index 00000000..c59d40d5 --- /dev/null +++ b/applications/external/nfc_rfid_detector/nfc_rfid_detector_app_i.c @@ -0,0 +1,40 @@ +#include "nfc_rfid_detector_app_i.h" + +#include + +#define TAG "NfcRfidDetector" + +void nfc_rfid_detector_app_field_presence_start(NfcRfidDetectorApp* app) { + furi_assert(app); + + // start the field presence rfid detection + furi_hal_rfid_field_detect_start(); + + // start the field presence nfc detection + furi_hal_nfc_exit_sleep(); + furi_hal_nfc_field_detect_start(); +} + +void nfc_rfid_detector_app_field_presence_stop(NfcRfidDetectorApp* app) { + furi_assert(app); + + // stop the field presence rfid detection + furi_hal_rfid_field_detect_stop(); + + // stop the field presence nfc detection + furi_hal_nfc_start_sleep(); +} + +bool nfc_rfid_detector_app_field_presence_is_nfc(NfcRfidDetectorApp* app) { + furi_assert(app); + + // check if the field presence is nfc + return furi_hal_nfc_field_is_present(); +} + +bool nfc_rfid_detector_app_field_presence_is_rfid(NfcRfidDetectorApp* app, uint32_t* frequency) { + furi_assert(app); + + // check if the field presence is rfid + return furi_hal_rfid_field_is_present(frequency); +} \ No newline at end of file diff --git a/applications/external/nfc_rfid_detector/nfc_rfid_detector_app_i.h b/applications/external/nfc_rfid_detector/nfc_rfid_detector_app_i.h new file mode 100644 index 00000000..72cb126d --- /dev/null +++ b/applications/external/nfc_rfid_detector/nfc_rfid_detector_app_i.h @@ -0,0 +1,30 @@ +#pragma once + +#include "helpers/nfc_rfid_detector_types.h" +#include "helpers/nfc_rfid_detector_event.h" + +#include "scenes/nfc_rfid_detector_scene.h" +#include +#include +#include +#include +#include +#include +#include "views/nfc_rfid_detector_view_field_presence.h" + +typedef struct NfcRfidDetectorApp NfcRfidDetectorApp; + +struct NfcRfidDetectorApp { + Gui* gui; + ViewDispatcher* view_dispatcher; + SceneManager* scene_manager; + NotificationApp* notifications; + Submenu* submenu; + Widget* widget; + NfcRfidDetectorFieldPresence* nfc_rfid_detector_field_presence; +}; + +void nfc_rfid_detector_app_field_presence_start(NfcRfidDetectorApp* app); +void nfc_rfid_detector_app_field_presence_stop(NfcRfidDetectorApp* app); +bool nfc_rfid_detector_app_field_presence_is_nfc(NfcRfidDetectorApp* app); +bool nfc_rfid_detector_app_field_presence_is_rfid(NfcRfidDetectorApp* app, uint32_t* frequency); \ No newline at end of file diff --git a/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene.c b/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene.c new file mode 100644 index 00000000..d75eb288 --- /dev/null +++ b/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene.c @@ -0,0 +1,31 @@ +#include "../nfc_rfid_detector_app_i.h" + +// Generate scene on_enter handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter, +void (*const nfc_rfid_detector_scene_on_enter_handlers[])(void*) = { +#include "nfc_rfid_detector_scene_config.h" +}; +#undef ADD_SCENE + +// Generate scene on_event handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event, +bool (*const nfc_rfid_detector_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = + { +#include "nfc_rfid_detector_scene_config.h" +}; +#undef ADD_SCENE + +// Generate scene on_exit handlers array +#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit, +void (*const nfc_rfid_detector_scene_on_exit_handlers[])(void* context) = { +#include "nfc_rfid_detector_scene_config.h" +}; +#undef ADD_SCENE + +// Initialize scene handlers configuration structure +const SceneManagerHandlers nfc_rfid_detector_scene_handlers = { + .on_enter_handlers = nfc_rfid_detector_scene_on_enter_handlers, + .on_event_handlers = nfc_rfid_detector_scene_on_event_handlers, + .on_exit_handlers = nfc_rfid_detector_scene_on_exit_handlers, + .scene_num = NfcRfidDetectorSceneNum, +}; diff --git a/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene.h b/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene.h new file mode 100644 index 00000000..74d324b4 --- /dev/null +++ b/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene.h @@ -0,0 +1,29 @@ +#pragma once + +#include + +// Generate scene id and total number +#define ADD_SCENE(prefix, name, id) NfcRfidDetectorScene##id, +typedef enum { +#include "nfc_rfid_detector_scene_config.h" + NfcRfidDetectorSceneNum, +} NfcRfidDetectorScene; +#undef ADD_SCENE + +extern const SceneManagerHandlers nfc_rfid_detector_scene_handlers; + +// Generate scene on_enter handlers declaration +#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*); +#include "nfc_rfid_detector_scene_config.h" +#undef ADD_SCENE + +// Generate scene on_event handlers declaration +#define ADD_SCENE(prefix, name, id) \ + bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event); +#include "nfc_rfid_detector_scene_config.h" +#undef ADD_SCENE + +// Generate scene on_exit handlers declaration +#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context); +#include "nfc_rfid_detector_scene_config.h" +#undef ADD_SCENE diff --git a/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene_about.c b/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene_about.c new file mode 100644 index 00000000..ddcb8aac --- /dev/null +++ b/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene_about.c @@ -0,0 +1,69 @@ +#include "../nfc_rfid_detector_app_i.h" + +void nfc_rfid_detector_scene_about_widget_callback( + GuiButtonType result, + InputType type, + void* context) { + NfcRfidDetectorApp* app = context; + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(app->view_dispatcher, result); + } +} + +void nfc_rfid_detector_scene_about_on_enter(void* context) { + NfcRfidDetectorApp* app = context; + + FuriString* temp_str; + temp_str = furi_string_alloc(); + furi_string_printf(temp_str, "\e#%s\n", "Information"); + + furi_string_cat_printf(temp_str, "Version: %s\n", NFC_RFID_DETECTOR_VERSION_APP); + furi_string_cat_printf(temp_str, "Developed by: %s\n", NFC_RFID_DETECTOR_DEVELOPED); + furi_string_cat_printf(temp_str, "Github: %s\n\n", NFC_RFID_DETECTOR_GITHUB); + + furi_string_cat_printf(temp_str, "\e#%s\n", "Description"); + furi_string_cat_printf( + temp_str, + "This application allows\nyou to determine what\ntype of electromagnetic\nfield the reader is using.\nFor LF RFID you can also\nsee the carrier frequency\n\n"); + + widget_add_text_box_element( + app->widget, + 0, + 0, + 128, + 14, + AlignCenter, + AlignBottom, + "\e#\e! \e!\n", + false); + widget_add_text_box_element( + app->widget, + 0, + 2, + 128, + 14, + AlignCenter, + AlignBottom, + "\e#\e! NFC/RFID detector \e!\n", + false); + widget_add_text_scroll_element(app->widget, 0, 16, 128, 50, furi_string_get_cstr(temp_str)); + furi_string_free(temp_str); + + view_dispatcher_switch_to_view(app->view_dispatcher, NfcRfidDetectorViewWidget); +} + +bool nfc_rfid_detector_scene_about_on_event(void* context, SceneManagerEvent event) { + NfcRfidDetectorApp* app = context; + bool consumed = false; + UNUSED(app); + UNUSED(event); + + return consumed; +} + +void nfc_rfid_detector_scene_about_on_exit(void* context) { + NfcRfidDetectorApp* app = context; + + // Clear views + widget_reset(app->widget); +} diff --git a/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene_config.h b/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene_config.h new file mode 100644 index 00000000..ab49ad5c --- /dev/null +++ b/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene_config.h @@ -0,0 +1,3 @@ +ADD_SCENE(nfc_rfid_detector, start, Start) +ADD_SCENE(nfc_rfid_detector, about, About) +ADD_SCENE(nfc_rfid_detector, field_presence, FieldPresence) diff --git a/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene_field_presence.c b/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene_field_presence.c new file mode 100644 index 00000000..ec53b5a0 --- /dev/null +++ b/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene_field_presence.c @@ -0,0 +1,60 @@ +#include "../nfc_rfid_detector_app_i.h" +#include "../views/nfc_rfid_detector_view_field_presence.h" + +void nfc_rfid_detector_scene_field_presence_callback( + NfcRfidDetectorCustomEvent event, + void* context) { + furi_assert(context); + NfcRfidDetectorApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, event); +} + +static const NotificationSequence notification_app_display_on = { + + &message_display_backlight_on, + NULL, +}; + +static void nfc_rfid_detector_scene_field_presence_update(void* context) { + furi_assert(context); + NfcRfidDetectorApp* app = context; + + uint32_t frequency = 0; + bool nfc_field = nfc_rfid_detector_app_field_presence_is_nfc(app); + bool rfid_field = nfc_rfid_detector_app_field_presence_is_rfid(app, &frequency); + + if(nfc_field || rfid_field) + notification_message(app->notifications, ¬ification_app_display_on); + + nfc_rfid_detector_view_field_presence_update( + app->nfc_rfid_detector_field_presence, nfc_field, rfid_field, frequency); +} + +void nfc_rfid_detector_scene_field_presence_on_enter(void* context) { + furi_assert(context); + NfcRfidDetectorApp* app = context; + + // Start detection of field presence + nfc_rfid_detector_app_field_presence_start(app); + + view_dispatcher_switch_to_view(app->view_dispatcher, NfcRfidDetectorViewFieldPresence); +} + +bool nfc_rfid_detector_scene_field_presence_on_event(void* context, SceneManagerEvent event) { + furi_assert(context); + NfcRfidDetectorApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeTick) { + nfc_rfid_detector_scene_field_presence_update(app); + } + + return consumed; +} + +void nfc_rfid_detector_scene_field_presence_on_exit(void* context) { + furi_assert(context); + NfcRfidDetectorApp* app = context; + // Stop detection of field presence + nfc_rfid_detector_app_field_presence_stop(app); +} diff --git a/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene_start.c b/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene_start.c new file mode 100644 index 00000000..7b71bd97 --- /dev/null +++ b/applications/external/nfc_rfid_detector/scenes/nfc_rfid_detector_scene_start.c @@ -0,0 +1,58 @@ +#include "../nfc_rfid_detector_app_i.h" + +typedef enum { + SubmenuIndexNfcRfidDetectorFieldPresence, + SubmenuIndexNfcRfidDetectorAbout, +} SubmenuIndex; + +void nfc_rfid_detector_scene_start_submenu_callback(void* context, uint32_t index) { + NfcRfidDetectorApp* app = context; + view_dispatcher_send_custom_event(app->view_dispatcher, index); +} + +void nfc_rfid_detector_scene_start_on_enter(void* context) { + UNUSED(context); + NfcRfidDetectorApp* app = context; + Submenu* submenu = app->submenu; + + submenu_add_item( + submenu, + "Detect field type", + SubmenuIndexNfcRfidDetectorFieldPresence, + nfc_rfid_detector_scene_start_submenu_callback, + app); + submenu_add_item( + submenu, + "About", + SubmenuIndexNfcRfidDetectorAbout, + nfc_rfid_detector_scene_start_submenu_callback, + app); + + submenu_set_selected_item( + submenu, scene_manager_get_scene_state(app->scene_manager, NfcRfidDetectorSceneStart)); + + view_dispatcher_switch_to_view(app->view_dispatcher, NfcRfidDetectorViewSubmenu); +} + +bool nfc_rfid_detector_scene_start_on_event(void* context, SceneManagerEvent event) { + NfcRfidDetectorApp* app = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubmenuIndexNfcRfidDetectorAbout) { + scene_manager_next_scene(app->scene_manager, NfcRfidDetectorSceneAbout); + consumed = true; + } else if(event.event == SubmenuIndexNfcRfidDetectorFieldPresence) { + scene_manager_next_scene(app->scene_manager, NfcRfidDetectorSceneFieldPresence); + consumed = true; + } + scene_manager_set_scene_state(app->scene_manager, NfcRfidDetectorSceneStart, event.event); + } + + return consumed; +} + +void nfc_rfid_detector_scene_start_on_exit(void* context) { + NfcRfidDetectorApp* app = context; + submenu_reset(app->submenu); +} diff --git a/applications/external/nfc_rfid_detector/views/nfc_rfid_detector_view_field_presence.c b/applications/external/nfc_rfid_detector/views/nfc_rfid_detector_view_field_presence.c new file mode 100644 index 00000000..e65eb836 --- /dev/null +++ b/applications/external/nfc_rfid_detector/views/nfc_rfid_detector_view_field_presence.c @@ -0,0 +1,164 @@ +#include "nfc_rfid_detector_view_field_presence.h" +#include "../nfc_rfid_detector_app_i.h" +#include + +#include +#include + +#define FIELD_FOUND_WEIGHT 5 + +typedef enum { + NfcRfidDetectorTypeFieldPresenceNfc, + NfcRfidDetectorTypeFieldPresenceRfid, +} NfcRfidDetectorTypeFieldPresence; + +static const Icon* NfcRfidDetectorFieldPresenceIcons[] = { + [NfcRfidDetectorTypeFieldPresenceNfc] = &I_NFC_detect_45x30, + [NfcRfidDetectorTypeFieldPresenceRfid] = &I_Rfid_detect_45x30, +}; + +struct NfcRfidDetectorFieldPresence { + View* view; +}; + +typedef struct { + uint8_t nfc_field; + uint8_t rfid_field; + uint32_t rfid_frequency; +} NfcRfidDetectorFieldPresenceModel; + +void nfc_rfid_detector_view_field_presence_update( + NfcRfidDetectorFieldPresence* instance, + bool nfc_field, + bool rfid_field, + uint32_t rfid_frequency) { + furi_assert(instance); + with_view_model( + instance->view, + NfcRfidDetectorFieldPresenceModel * model, + { + if(nfc_field) { + model->nfc_field = FIELD_FOUND_WEIGHT; + } else if(model->nfc_field) { + model->nfc_field--; + } + if(rfid_field) { + model->rfid_field = FIELD_FOUND_WEIGHT; + model->rfid_frequency = rfid_frequency; + } else if(model->rfid_field) { + model->rfid_field--; + } + }, + true); +} + +void nfc_rfid_detector_view_field_presence_draw( + Canvas* canvas, + NfcRfidDetectorFieldPresenceModel* model) { + canvas_clear(canvas); + canvas_set_color(canvas, ColorBlack); + + if(!model->nfc_field && !model->rfid_field) { + canvas_draw_icon(canvas, 0, 16, &I_Modern_reader_18x34); + canvas_draw_icon(canvas, 22, 12, &I_Move_flipper_26x39); + canvas_set_font(canvas, FontSecondary); + canvas_draw_str(canvas, 56, 36, "Touch the reader"); + } else { + if(model->nfc_field) { + canvas_set_font(canvas, FontPrimary); + canvas_draw_str(canvas, 21, 10, "NFC"); + canvas_draw_icon( + canvas, + 9, + 17, + NfcRfidDetectorFieldPresenceIcons[NfcRfidDetectorTypeFieldPresenceNfc]); + canvas_set_font(canvas, FontSecondary); + canvas_draw_str(canvas, 9, 62, "13,56 MHz"); + } + + if(model->rfid_field) { + char str[16]; + snprintf(str, sizeof(str), "%.02f KHz", (double)model->rfid_frequency / 1000); + canvas_set_font(canvas, FontPrimary); + canvas_draw_str(canvas, 76, 10, "LF RFID"); + canvas_draw_icon( + canvas, + 71, + 17, + NfcRfidDetectorFieldPresenceIcons[NfcRfidDetectorTypeFieldPresenceRfid]); + canvas_set_font(canvas, FontSecondary); + canvas_draw_str(canvas, 69, 62, str); + } + } +} + +bool nfc_rfid_detector_view_field_presence_input(InputEvent* event, void* context) { + furi_assert(context); + NfcRfidDetectorFieldPresence* instance = context; + UNUSED(instance); + + if(event->key == InputKeyBack) { + return false; + } + + return true; +} + +void nfc_rfid_detector_view_field_presence_enter(void* context) { + furi_assert(context); + NfcRfidDetectorFieldPresence* instance = context; + with_view_model( + instance->view, + NfcRfidDetectorFieldPresenceModel * model, + { + model->nfc_field = 0; + model->rfid_field = 0; + model->rfid_frequency = 0; + }, + true); +} + +void nfc_rfid_detector_view_field_presence_exit(void* context) { + furi_assert(context); + NfcRfidDetectorFieldPresence* instance = context; + UNUSED(instance); +} + +NfcRfidDetectorFieldPresence* nfc_rfid_detector_view_field_presence_alloc() { + NfcRfidDetectorFieldPresence* instance = malloc(sizeof(NfcRfidDetectorFieldPresence)); + + // View allocation and configuration + instance->view = view_alloc(); + + view_allocate_model( + instance->view, ViewModelTypeLocking, sizeof(NfcRfidDetectorFieldPresenceModel)); + view_set_context(instance->view, instance); + view_set_draw_callback( + instance->view, (ViewDrawCallback)nfc_rfid_detector_view_field_presence_draw); + view_set_input_callback(instance->view, nfc_rfid_detector_view_field_presence_input); + view_set_enter_callback(instance->view, nfc_rfid_detector_view_field_presence_enter); + view_set_exit_callback(instance->view, nfc_rfid_detector_view_field_presence_exit); + + with_view_model( + instance->view, + NfcRfidDetectorFieldPresenceModel * model, + { + model->nfc_field = 0; + model->rfid_field = 0; + model->rfid_frequency = 0; + }, + true); + return instance; +} + +void nfc_rfid_detector_view_field_presence_free(NfcRfidDetectorFieldPresence* instance) { + furi_assert(instance); + + view_free(instance->view); + free(instance); +} + +View* nfc_rfid_detector_view_field_presence_get_view(NfcRfidDetectorFieldPresence* instance) { + furi_assert(instance); + return instance->view; +} diff --git a/applications/external/nfc_rfid_detector/views/nfc_rfid_detector_view_field_presence.h b/applications/external/nfc_rfid_detector/views/nfc_rfid_detector_view_field_presence.h new file mode 100644 index 00000000..0ddb4e2c --- /dev/null +++ b/applications/external/nfc_rfid_detector/views/nfc_rfid_detector_view_field_presence.h @@ -0,0 +1,19 @@ +#pragma once + +#include +#include "../helpers/nfc_rfid_detector_types.h" +#include "../helpers/nfc_rfid_detector_event.h" + +typedef struct NfcRfidDetectorFieldPresence NfcRfidDetectorFieldPresence; + +void nfc_rfid_detector_view_field_presence_update( + NfcRfidDetectorFieldPresence* instance, + bool nfc_field, + bool rfid_field, + uint32_t rfid_frequency); + +NfcRfidDetectorFieldPresence* nfc_rfid_detector_view_field_presence_alloc(); + +void nfc_rfid_detector_view_field_presence_free(NfcRfidDetectorFieldPresence* instance); + +View* nfc_rfid_detector_view_field_presence_get_view(NfcRfidDetectorFieldPresence* instance); diff --git a/firmware/targets/f18/api_symbols.csv b/firmware/targets/f18/api_symbols.csv index 56a7f678..0b4e2d6d 100644 --- a/firmware/targets/f18/api_symbols.csv +++ b/firmware/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,31.0,, +Version,+,31.1,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 0f782e96..5ba66407 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,+,31.0,, +Version,+,31.1,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -1220,6 +1220,8 @@ Function,+,furi_hal_mpu_protect_disable,void,FuriHalMpuRegion Function,+,furi_hal_mpu_protect_no_access,void,"FuriHalMpuRegion, uint32_t, FuriHalMPURegionSize" Function,+,furi_hal_mpu_protect_read_only,void,"FuriHalMpuRegion, uint32_t, FuriHalMPURegionSize" Function,+,furi_hal_nfc_activate_nfca,_Bool,"uint32_t, uint32_t*" +Function,+,furi_hal_nfc_field_is_present,_Bool, +Function,+,furi_hal_nfc_field_detect_start,void, Function,-,furi_hal_nfc_deinit,void, Function,+,furi_hal_nfc_detect,_Bool,"FuriHalNfcDevData*, uint32_t" Function,+,furi_hal_nfc_emulate_nfca,_Bool,"uint8_t*, uint8_t, uint8_t*, uint8_t, FuriHalNfcEmulateCallback, void*, uint32_t" @@ -1304,6 +1306,9 @@ Function,-,furi_hal_resources_init_early,void, Function,+,furi_hal_rfid_comp_set_callback,void,"FuriHalRfidCompCallback, void*" Function,+,furi_hal_rfid_comp_start,void, Function,+,furi_hal_rfid_comp_stop,void, +Function,+,furi_hal_rfid_field_is_present,_Bool,uint32_t* +Function,+,furi_hal_rfid_field_detect_start,void, +Function,+,furi_hal_rfid_field_detect_stop,void, Function,-,furi_hal_rfid_init,void, Function,+,furi_hal_rfid_pin_pull_pulldown,void, Function,+,furi_hal_rfid_pin_pull_release,void, diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc.c b/firmware/targets/f7/furi_hal/furi_hal_nfc.c index c4e7ad9f..b249c865 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_nfc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_nfc.c @@ -819,3 +819,17 @@ FuriHalNfcReturn furi_hal_nfc_ll_txrx_bits( void furi_hal_nfc_ll_poll() { rfalWorker(); } + +void furi_hal_nfc_field_detect_start() { + st25r3916WriteRegister( + ST25R3916_REG_OP_CONTROL, + ST25R3916_REG_OP_CONTROL_en | ST25R3916_REG_OP_CONTROL_en_fd_mask); + st25r3916WriteRegister(ST25R3916_REG_MODE, ST25R3916_REG_MODE_targ | ST25R3916_REG_MODE_om0); +} + +bool furi_hal_nfc_field_is_present() { + return st25r3916CheckReg( + ST25R3916_REG_AUX_DISPLAY, + ST25R3916_REG_AUX_DISPLAY_efd_o, + ST25R3916_REG_AUX_DISPLAY_efd_o); +} \ No newline at end of file diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc.h b/firmware/targets/f7/furi_hal/furi_hal_nfc.h index dc3f873f..c87f04a9 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_nfc.h +++ b/firmware/targets/f7/furi_hal/furi_hal_nfc.h @@ -423,6 +423,10 @@ FuriHalNfcReturn furi_hal_nfc_ll_txrx_bits( void furi_hal_nfc_ll_poll(); +void furi_hal_nfc_field_detect_start(); + +bool furi_hal_nfc_field_is_present(); + #ifdef __cplusplus } #endif diff --git a/firmware/targets/f7/furi_hal/furi_hal_rfid.c b/firmware/targets/f7/furi_hal/furi_hal_rfid.c index fa0c19b0..67f11d6f 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_rfid.c +++ b/firmware/targets/f7/furi_hal/furi_hal_rfid.c @@ -25,6 +25,19 @@ #define RFID_CAPTURE_IND_CH LL_TIM_CHANNEL_CH3 #define RFID_CAPTURE_DIR_CH LL_TIM_CHANNEL_CH4 +// Field presence detection +#define FURI_HAL_RFID_FIELD_FREQUENCY_MIN 80000 +#define FURI_HAL_RFID_FIELD_FREQUENCY_MAX 200000 + +#define FURI_HAL_RFID_FIELD_COUNTER_TIMER TIM2 +#define FURI_HAL_RFID_FIELD_COUNTER_TIMER_BUS FuriHalBusTIM2 +#define FURI_HAL_RFID_FIELD_COUNTER_TIMER_CHANNEL LL_TIM_CHANNEL_CH3 + +#define FURI_HAL_RFID_FIELD_TIMEOUT_TIMER TIM1 +#define FURI_HAL_RFID_FIELD_TIMEOUT_TIMER_BUS FuriHalBusTIM1 + +#define FURI_HAL_RFID_FIELD_DMAMUX_DMA LL_DMAMUX_REQ_TIM1_UP + /* DMA Channels definition */ #define RFID_DMA DMA2 #define RFID_DMA_CH1_CHANNEL LL_DMA_CHANNEL_1 @@ -33,10 +46,16 @@ #define RFID_DMA_CH1_DEF RFID_DMA, RFID_DMA_CH1_CHANNEL #define RFID_DMA_CH2_DEF RFID_DMA, RFID_DMA_CH2_CHANNEL +typedef struct { + uint32_t counter; + uint32_t set_tim_counter_cnt; +} FuriHalRfidField; + typedef struct { FuriHalRfidDMACallback dma_callback; FuriHalRfidReadCaptureCallback read_capture_callback; void* context; + FuriHalRfidField field; } FuriHalRfid; FuriHalRfid* furi_hal_rfid = NULL; @@ -51,6 +70,8 @@ FuriHalRfid* furi_hal_rfid = NULL; void furi_hal_rfid_init() { furi_assert(furi_hal_rfid == NULL); furi_hal_rfid = malloc(sizeof(FuriHalRfid)); + furi_hal_rfid->field.counter = 0; + furi_hal_rfid->field.set_tim_counter_cnt = 0; furi_hal_rfid_pins_reset(); @@ -133,6 +154,23 @@ static void furi_hal_rfid_pins_read() { furi_hal_gpio_init(&gpio_rfid_data_in, GpioModeAnalog, GpioPullNo, GpioSpeedLow); } +static void furi_hal_rfid_pins_field() { + // ibutton low + furi_hal_ibutton_pin_configure(); + furi_hal_ibutton_pin_write(false); + + // pull pin to timer out + furi_hal_gpio_init(&gpio_nfc_irq_rfid_pull, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_write(&gpio_nfc_irq_rfid_pull, false); + + // pull rfid antenna from carrier side + furi_hal_gpio_init(&gpio_rfid_carrier_out, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); + furi_hal_gpio_write(&gpio_rfid_carrier_out, false); + + furi_hal_gpio_init_ex( + &gpio_rfid_carrier, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn2TIM2); +} + void furi_hal_rfid_pin_pull_release() { furi_hal_gpio_write(&gpio_nfc_irq_rfid_pull, true); } @@ -427,3 +465,124 @@ void COMP_IRQHandler() { furi_hal_rfid_comp_callback_context); } } + +static void furi_hal_rfid_field_tim_setup() { + // setup timer counter + furi_hal_bus_enable(FURI_HAL_RFID_FIELD_COUNTER_TIMER_BUS); + + LL_TIM_SetPrescaler(FURI_HAL_RFID_FIELD_COUNTER_TIMER, 0); + LL_TIM_SetCounterMode(FURI_HAL_RFID_FIELD_COUNTER_TIMER, LL_TIM_COUNTERMODE_UP); + LL_TIM_SetAutoReload(FURI_HAL_RFID_FIELD_COUNTER_TIMER, 0xFFFFFFFF); + LL_TIM_DisableARRPreload(FURI_HAL_RFID_FIELD_COUNTER_TIMER); + LL_TIM_SetRepetitionCounter(FURI_HAL_RFID_FIELD_COUNTER_TIMER, 0); + + LL_TIM_SetClockDivision(FURI_HAL_RFID_FIELD_COUNTER_TIMER, LL_TIM_CLOCKDIVISION_DIV1); + LL_TIM_SetClockSource(FURI_HAL_RFID_FIELD_COUNTER_TIMER, LL_TIM_CLOCKSOURCE_EXT_MODE2); + LL_TIM_ConfigETR( + FURI_HAL_RFID_FIELD_COUNTER_TIMER, + LL_TIM_ETR_POLARITY_INVERTED, + LL_TIM_ETR_PRESCALER_DIV1, + LL_TIM_ETR_FILTER_FDIV1); + + LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0}; + TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1; + TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_ENABLE; + TIM_OC_InitStruct.CompareValue = 1; + LL_TIM_OC_Init( + FURI_HAL_RFID_FIELD_COUNTER_TIMER, + FURI_HAL_RFID_FIELD_COUNTER_TIMER_CHANNEL, + &TIM_OC_InitStruct); + + LL_TIM_GenerateEvent_UPDATE(FURI_HAL_RFID_FIELD_COUNTER_TIMER); + LL_TIM_OC_SetPolarity( + FURI_HAL_RFID_FIELD_COUNTER_TIMER, + FURI_HAL_RFID_FIELD_COUNTER_TIMER_CHANNEL, + LL_TIM_OCPOLARITY_HIGH); + LL_TIM_EnableDMAReq_UPDATE(FURI_HAL_RFID_FIELD_COUNTER_TIMER); + + // setup timer timeouts dma + furi_hal_bus_enable(FURI_HAL_RFID_FIELD_TIMEOUT_TIMER_BUS); + + LL_TIM_SetPrescaler(FURI_HAL_RFID_FIELD_TIMEOUT_TIMER, 64000 - 1); + LL_TIM_SetCounterMode(FURI_HAL_RFID_FIELD_TIMEOUT_TIMER, LL_TIM_COUNTERMODE_UP); + LL_TIM_SetAutoReload(FURI_HAL_RFID_FIELD_TIMEOUT_TIMER, 100 - 1); // 100 ms + LL_TIM_SetClockDivision(FURI_HAL_RFID_FIELD_TIMEOUT_TIMER, LL_TIM_CLOCKDIVISION_DIV1); + LL_TIM_SetClockSource(FURI_HAL_RFID_FIELD_TIMEOUT_TIMER, LL_TIM_CLOCKSOURCE_INTERNAL); + + LL_TIM_DisableARRPreload(FURI_HAL_RFID_FIELD_TIMEOUT_TIMER); + + LL_TIM_EnableDMAReq_UPDATE(FURI_HAL_RFID_FIELD_TIMEOUT_TIMER); + LL_TIM_GenerateEvent_UPDATE(FURI_HAL_RFID_FIELD_TIMEOUT_TIMER); +} + +void furi_hal_rfid_field_detect_start(void) { + // setup pins + furi_hal_rfid_pins_field(); + + // configure timer + furi_hal_rfid_field_tim_setup(); + + // configure DMA "TIM_COUNTER_CNT -> counter" + LL_DMA_SetMemoryAddress(RFID_DMA_CH1_DEF, (uint32_t) & (furi_hal_rfid->field.counter)); + LL_DMA_SetPeriphAddress( + RFID_DMA_CH1_DEF, (uint32_t) & (FURI_HAL_RFID_FIELD_COUNTER_TIMER->CNT)); + LL_DMA_ConfigTransfer( + RFID_DMA_CH1_DEF, + LL_DMA_DIRECTION_PERIPH_TO_MEMORY | LL_DMA_MODE_CIRCULAR | LL_DMA_PERIPH_NOINCREMENT | + LL_DMA_MEMORY_NOINCREMENT | LL_DMA_PDATAALIGN_WORD | LL_DMA_MDATAALIGN_WORD | + LL_DMA_PRIORITY_MEDIUM); + LL_DMA_SetDataLength(RFID_DMA_CH1_DEF, 1); + LL_DMA_SetPeriphRequest(RFID_DMA_CH1_DEF, FURI_HAL_RFID_FIELD_DMAMUX_DMA); + LL_DMA_EnableChannel(RFID_DMA_CH1_DEF); + + // configure DMA "mem -> TIM_COUNTER_CNT" + LL_DMA_SetMemoryAddress( + RFID_DMA_CH2_DEF, (uint32_t) & (furi_hal_rfid->field.set_tim_counter_cnt)); + LL_DMA_SetPeriphAddress( + RFID_DMA_CH2_DEF, (uint32_t) & (FURI_HAL_RFID_FIELD_COUNTER_TIMER->CNT)); + LL_DMA_ConfigTransfer( + RFID_DMA_CH2_DEF, + LL_DMA_DIRECTION_MEMORY_TO_PERIPH | LL_DMA_MODE_CIRCULAR | LL_DMA_PERIPH_NOINCREMENT | + LL_DMA_MEMORY_NOINCREMENT | LL_DMA_PDATAALIGN_WORD | LL_DMA_MDATAALIGN_WORD | + LL_DMA_PRIORITY_LOW); + LL_DMA_SetDataLength(RFID_DMA_CH2_DEF, 1); + LL_DMA_SetPeriphRequest(RFID_DMA_CH2_DEF, FURI_HAL_RFID_FIELD_DMAMUX_DMA); + LL_DMA_EnableChannel(RFID_DMA_CH2_DEF); + + // start tim counter + LL_TIM_EnableAllOutputs(FURI_HAL_RFID_FIELD_COUNTER_TIMER); + + LL_TIM_SetCounter(FURI_HAL_RFID_FIELD_COUNTER_TIMER, 0); + LL_TIM_EnableCounter(FURI_HAL_RFID_FIELD_COUNTER_TIMER); + + // start tim timeout + LL_TIM_SetCounter(FURI_HAL_RFID_FIELD_TIMEOUT_TIMER, 0); + LL_TIM_EnableCounter(FURI_HAL_RFID_FIELD_TIMEOUT_TIMER); + LL_TIM_EnableIT_UPDATE(FURI_HAL_RFID_FIELD_TIMEOUT_TIMER); +} + +void furi_hal_rfid_field_detect_stop(void) { + LL_TIM_DisableCounter(FURI_HAL_RFID_FIELD_COUNTER_TIMER); + LL_TIM_DisableAllOutputs(FURI_HAL_RFID_FIELD_COUNTER_TIMER); + + LL_TIM_DisableCounter(FURI_HAL_RFID_FIELD_TIMEOUT_TIMER); + + FURI_CRITICAL_ENTER(); + + LL_DMA_DeInit(RFID_DMA_CH1_DEF); + LL_DMA_DeInit(RFID_DMA_CH2_DEF); + + furi_hal_bus_disable(FURI_HAL_RFID_FIELD_COUNTER_TIMER_BUS); + furi_hal_bus_disable(FURI_HAL_RFID_FIELD_TIMEOUT_TIMER_BUS); + + furi_hal_rfid_pins_reset(); + + FURI_CRITICAL_EXIT(); +} + +bool furi_hal_rfid_field_is_present(uint32_t* frequency) { + *frequency = furi_hal_rfid->field.counter * 10; + return ( + (*frequency >= FURI_HAL_RFID_FIELD_FREQUENCY_MIN) && + (*frequency <= FURI_HAL_RFID_FIELD_FREQUENCY_MAX)); +} \ No newline at end of file diff --git a/firmware/targets/f7/furi_hal/furi_hal_rfid.h b/firmware/targets/f7/furi_hal/furi_hal_rfid.h index 78d9b665..7087ba99 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_rfid.h +++ b/firmware/targets/f7/furi_hal/furi_hal_rfid.h @@ -87,6 +87,20 @@ typedef void (*FuriHalRfidCompCallback)(bool level, void* context); /** Set comparator callback */ void furi_hal_rfid_comp_set_callback(FuriHalRfidCompCallback callback, void* context); +/** Start/Enable Field Presence detect */ +void furi_hal_rfid_field_detect_start(); + +/** Stop/Disable Field Presence detect */ +void furi_hal_rfid_field_detect_stop(); + +/** Check Field Presence + * + * @param[out] frequency pointer to frequency value to be set if filed detected + * + * @return true if field is present, false if not + */ +bool furi_hal_rfid_field_is_present(uint32_t* frequency); + #ifdef __cplusplus } #endif