Merge branch 'dev' into release-candidate
This commit is contained in:
		
						commit
						0d35596d96
					
				| @ -4,8 +4,6 @@ | |||||||
| #include <furi.h> | #include <furi.h> | ||||||
| #include <furi_hal.h> | #include <furi_hal.h> | ||||||
| 
 | 
 | ||||||
| #include <loader/loader.h> |  | ||||||
| 
 |  | ||||||
| #include "animations/animation_manager.h" | #include "animations/animation_manager.h" | ||||||
| #include "desktop/scenes/desktop_scene.h" | #include "desktop/scenes/desktop_scene.h" | ||||||
| #include "desktop/scenes/desktop_scene_i.h" | #include "desktop/scenes/desktop_scene_i.h" | ||||||
| @ -15,6 +13,18 @@ | |||||||
| #include "desktop_i.h" | #include "desktop_i.h" | ||||||
| #include "desktop_helpers.h" | #include "desktop_helpers.h" | ||||||
| 
 | 
 | ||||||
|  | static void desktop_loader_callback(const void* message, void* context) { | ||||||
|  |     furi_assert(context); | ||||||
|  |     Desktop* desktop = context; | ||||||
|  |     const LoaderEvent* event = message; | ||||||
|  | 
 | ||||||
|  |     if(event->type == LoaderEventTypeApplicationStarted) { | ||||||
|  |         view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopGlobalBeforeAppStarted); | ||||||
|  |     } else if(event->type == LoaderEventTypeApplicationStopped) { | ||||||
|  |         view_dispatcher_send_custom_event(desktop->view_dispatcher, DesktopGlobalAfterAppFinished); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static void desktop_lock_icon_callback(Canvas* canvas, void* context) { | static void desktop_lock_icon_callback(Canvas* canvas, void* context) { | ||||||
|     furi_assert(canvas); |     furi_assert(canvas); | ||||||
|     canvas_draw_icon(canvas, 0, 0, &I_Lock_8x8); |     canvas_draw_icon(canvas, 0, 0, &I_Lock_8x8); | ||||||
| @ -23,6 +33,16 @@ static void desktop_lock_icon_callback(Canvas* canvas, void* context) { | |||||||
| static bool desktop_custom_event_callback(void* context, uint32_t event) { | static bool desktop_custom_event_callback(void* context, uint32_t event) { | ||||||
|     furi_assert(context); |     furi_assert(context); | ||||||
|     Desktop* desktop = (Desktop*)context; |     Desktop* desktop = (Desktop*)context; | ||||||
|  | 
 | ||||||
|  |     switch(event) { | ||||||
|  |     case DesktopGlobalBeforeAppStarted: | ||||||
|  |         animation_manager_unload_and_stall_animation(desktop->animation_manager); | ||||||
|  |         return true; | ||||||
|  |     case DesktopGlobalAfterAppFinished: | ||||||
|  |         animation_manager_load_and_continue_animation(desktop->animation_manager); | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     return scene_manager_handle_custom_event(desktop->scene_manager, event); |     return scene_manager_handle_custom_event(desktop->scene_manager, event); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -41,7 +61,6 @@ static void desktop_tick_event_callback(void* context) { | |||||||
| Desktop* desktop_alloc() { | Desktop* desktop_alloc() { | ||||||
|     Desktop* desktop = malloc(sizeof(Desktop)); |     Desktop* desktop = malloc(sizeof(Desktop)); | ||||||
| 
 | 
 | ||||||
|     desktop->unload_animation_semaphore = osSemaphoreNew(1, 0, NULL); |  | ||||||
|     desktop->animation_manager = animation_manager_alloc(); |     desktop->animation_manager = animation_manager_alloc(); | ||||||
|     desktop->gui = furi_record_open("gui"); |     desktop->gui = furi_record_open("gui"); | ||||||
|     desktop->scene_thread = furi_thread_alloc(); |     desktop->scene_thread = furi_thread_alloc(); | ||||||
| @ -122,12 +141,13 @@ Desktop* desktop_alloc() { | |||||||
|     gui_add_view_port(desktop->gui, desktop->lock_viewport, GuiLayerStatusBarLeft); |     gui_add_view_port(desktop->gui, desktop->lock_viewport, GuiLayerStatusBarLeft); | ||||||
| 
 | 
 | ||||||
|     // Special case: autostart application is already running
 |     // Special case: autostart application is already running
 | ||||||
|     Loader* loader = furi_record_open("loader"); |     desktop->loader = furi_record_open("loader"); | ||||||
|     if(loader_is_locked(loader) && |     if(loader_is_locked(desktop->loader) && | ||||||
|        animation_manager_is_animation_loaded(desktop->animation_manager)) { |        animation_manager_is_animation_loaded(desktop->animation_manager)) { | ||||||
|         animation_manager_unload_and_stall_animation(desktop->animation_manager); |         animation_manager_unload_and_stall_animation(desktop->animation_manager); | ||||||
|     } |     } | ||||||
|     furi_record_close("loader"); |     desktop->app_start_stop_subscription = furi_pubsub_subscribe( | ||||||
|  |         loader_get_pubsub(desktop->loader), desktop_loader_callback, desktop); | ||||||
| 
 | 
 | ||||||
|     return desktop; |     return desktop; | ||||||
| } | } | ||||||
| @ -135,6 +155,11 @@ Desktop* desktop_alloc() { | |||||||
| void desktop_free(Desktop* desktop) { | void desktop_free(Desktop* desktop) { | ||||||
|     furi_assert(desktop); |     furi_assert(desktop); | ||||||
| 
 | 
 | ||||||
|  |     furi_pubsub_unsubscribe( | ||||||
|  |         loader_get_pubsub(desktop->loader), desktop->app_start_stop_subscription); | ||||||
|  |     desktop->loader = NULL; | ||||||
|  |     furi_record_close("loader"); | ||||||
|  | 
 | ||||||
|     view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdMain); |     view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdMain); | ||||||
|     view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdLockMenu); |     view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdLockMenu); | ||||||
|     view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdLocked); |     view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdLocked); | ||||||
| @ -159,8 +184,6 @@ void desktop_free(Desktop* desktop) { | |||||||
|     popup_free(desktop->hw_mismatch_popup); |     popup_free(desktop->hw_mismatch_popup); | ||||||
|     desktop_view_pin_timeout_free(desktop->pin_timeout_view); |     desktop_view_pin_timeout_free(desktop->pin_timeout_view); | ||||||
| 
 | 
 | ||||||
|     osSemaphoreDelete(desktop->unload_animation_semaphore); |  | ||||||
| 
 |  | ||||||
|     furi_record_close("gui"); |     furi_record_close("gui"); | ||||||
|     desktop->gui = NULL; |     desktop->gui = NULL; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -18,6 +18,8 @@ | |||||||
| #include <gui/modules/popup.h> | #include <gui/modules/popup.h> | ||||||
| #include <gui/scene_manager.h> | #include <gui/scene_manager.h> | ||||||
| 
 | 
 | ||||||
|  | #include <loader/loader.h> | ||||||
|  | 
 | ||||||
| #define STATUS_BAR_Y_SHIFT 13 | #define STATUS_BAR_Y_SHIFT 13 | ||||||
| 
 | 
 | ||||||
| typedef enum { | typedef enum { | ||||||
| @ -57,7 +59,7 @@ struct Desktop { | |||||||
|     ViewPort* lock_viewport; |     ViewPort* lock_viewport; | ||||||
| 
 | 
 | ||||||
|     AnimationManager* animation_manager; |     AnimationManager* animation_manager; | ||||||
|     osSemaphoreId_t unload_animation_semaphore; |     Loader* loader; | ||||||
|     FuriPubSubSubscription* app_start_stop_subscription; |     FuriPubSubSubscription* app_start_stop_subscription; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -60,10 +60,8 @@ bool desktop_scene_lock_menu_on_event(void* context, SceneManagerEvent event) { | |||||||
|                     desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_FIRST_ENTER); |                     desktop->scene_manager, DesktopSceneLocked, SCENE_LOCKED_FIRST_ENTER); | ||||||
|                 scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked); |                 scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked); | ||||||
|             } else { |             } else { | ||||||
|                 Loader* loader = furi_record_open("loader"); |  | ||||||
|                 LoaderStatus status = |                 LoaderStatus status = | ||||||
|                     loader_start(loader, "Desktop", DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG); |                     loader_start(desktop->loader, "Desktop", DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG); | ||||||
|                 furi_record_close("loader"); |  | ||||||
|                 if(status == LoaderStatusOk) { |                 if(status == LoaderStatusOk) { | ||||||
|                     scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 1); |                     scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 1); | ||||||
|                 } else { |                 } else { | ||||||
|  | |||||||
| @ -12,21 +12,6 @@ | |||||||
| 
 | 
 | ||||||
| #define TAG "DesktopSrv" | #define TAG "DesktopSrv" | ||||||
| 
 | 
 | ||||||
| static void desktop_scene_main_app_started_callback(const void* message, void* context) { |  | ||||||
|     furi_assert(context); |  | ||||||
|     Desktop* desktop = context; |  | ||||||
|     const LoaderEvent* event = message; |  | ||||||
| 
 |  | ||||||
|     if(event->type == LoaderEventTypeApplicationStarted) { |  | ||||||
|         view_dispatcher_send_custom_event( |  | ||||||
|             desktop->view_dispatcher, DesktopMainEventBeforeAppStarted); |  | ||||||
|         osSemaphoreAcquire(desktop->unload_animation_semaphore, osWaitForever); |  | ||||||
|     } else if(event->type == LoaderEventTypeApplicationStopped) { |  | ||||||
|         view_dispatcher_send_custom_event( |  | ||||||
|             desktop->view_dispatcher, DesktopMainEventAfterAppFinished); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void desktop_scene_main_new_idle_animation_callback(void* context) { | static void desktop_scene_main_new_idle_animation_callback(void* context) { | ||||||
|     furi_assert(context); |     furi_assert(context); | ||||||
|     Desktop* desktop = context; |     Desktop* desktop = context; | ||||||
| @ -85,12 +70,6 @@ void desktop_scene_main_on_enter(void* context) { | |||||||
|     animation_manager_set_interact_callback( |     animation_manager_set_interact_callback( | ||||||
|         desktop->animation_manager, desktop_scene_main_interact_animation_callback); |         desktop->animation_manager, desktop_scene_main_interact_animation_callback); | ||||||
| 
 | 
 | ||||||
|     furi_assert(osSemaphoreGetCount(desktop->unload_animation_semaphore) == 0); |  | ||||||
|     Loader* loader = furi_record_open("loader"); |  | ||||||
|     desktop->app_start_stop_subscription = furi_pubsub_subscribe( |  | ||||||
|         loader_get_pubsub(loader), desktop_scene_main_app_started_callback, desktop); |  | ||||||
|     furi_record_close("loader"); |  | ||||||
| 
 |  | ||||||
|     desktop_main_set_callback(main_view, desktop_scene_main_callback, desktop); |     desktop_main_set_callback(main_view, desktop_scene_main_callback, desktop); | ||||||
| 
 | 
 | ||||||
|     view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdMain); |     view_dispatcher_switch_to_view(desktop->view_dispatcher, DesktopViewIdMain); | ||||||
| @ -127,13 +106,11 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { | |||||||
|         case DesktopMainEventOpenFavorite: |         case DesktopMainEventOpenFavorite: | ||||||
|             LOAD_DESKTOP_SETTINGS(&desktop->settings); |             LOAD_DESKTOP_SETTINGS(&desktop->settings); | ||||||
|             if(desktop->settings.favorite < FLIPPER_APPS_COUNT) { |             if(desktop->settings.favorite < FLIPPER_APPS_COUNT) { | ||||||
|                 Loader* loader = furi_record_open("loader"); |                 LoaderStatus status = loader_start( | ||||||
|                 LoaderStatus status = |                     desktop->loader, FLIPPER_APPS[desktop->settings.favorite].name, NULL); | ||||||
|                     loader_start(loader, FLIPPER_APPS[desktop->settings.favorite].name, NULL); |  | ||||||
|                 if(status != LoaderStatusOk) { |                 if(status != LoaderStatusOk) { | ||||||
|                     FURI_LOG_E(TAG, "loader_start failed: %d", status); |                     FURI_LOG_E(TAG, "loader_start failed: %d", status); | ||||||
|                 } |                 } | ||||||
|                 furi_record_close("loader"); |  | ||||||
|             } else { |             } else { | ||||||
|                 FURI_LOG_E(TAG, "Can't find favorite application"); |                 FURI_LOG_E(TAG, "Can't find favorite application"); | ||||||
|             } |             } | ||||||
| @ -152,15 +129,6 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { | |||||||
|             animation_manager_interact_process(desktop->animation_manager); |             animation_manager_interact_process(desktop->animation_manager); | ||||||
|             consumed = true; |             consumed = true; | ||||||
|             break; |             break; | ||||||
|         case DesktopMainEventBeforeAppStarted: |  | ||||||
|             animation_manager_unload_and_stall_animation(desktop->animation_manager); |  | ||||||
|             osSemaphoreRelease(desktop->unload_animation_semaphore); |  | ||||||
|             consumed = true; |  | ||||||
|             break; |  | ||||||
|         case DesktopMainEventAfterAppFinished: |  | ||||||
|             animation_manager_load_and_continue_animation(desktop->animation_manager); |  | ||||||
|             consumed = true; |  | ||||||
|             break; |  | ||||||
|         case DesktopLockedEventUpdate: |         case DesktopLockedEventUpdate: | ||||||
|             desktop_view_locked_update(desktop->locked_view); |             desktop_view_locked_update(desktop->locked_view); | ||||||
|             consumed = true; |             consumed = true; | ||||||
| @ -177,16 +145,6 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { | |||||||
| void desktop_scene_main_on_exit(void* context) { | void desktop_scene_main_on_exit(void* context) { | ||||||
|     Desktop* desktop = (Desktop*)context; |     Desktop* desktop = (Desktop*)context; | ||||||
| 
 | 
 | ||||||
|     /**
 |  | ||||||
|      * We're allowed to leave this scene only when any other app & loader |  | ||||||
|      * is finished, that's why we can be sure there is no task waiting |  | ||||||
|      * for start/stop semaphore |  | ||||||
|      */ |  | ||||||
|     Loader* loader = furi_record_open("loader"); |  | ||||||
|     furi_pubsub_unsubscribe(loader_get_pubsub(loader), desktop->app_start_stop_subscription); |  | ||||||
|     furi_record_close("loader"); |  | ||||||
|     furi_assert(osSemaphoreGetCount(desktop->unload_animation_semaphore) == 0); |  | ||||||
| 
 |  | ||||||
|     animation_manager_set_new_idle_callback(desktop->animation_manager, NULL); |     animation_manager_set_new_idle_callback(desktop->animation_manager, NULL); | ||||||
|     animation_manager_set_check_callback(desktop->animation_manager, NULL); |     animation_manager_set_check_callback(desktop->animation_manager, NULL); | ||||||
|     animation_manager_set_interact_callback(desktop->animation_manager, NULL); |     animation_manager_set_interact_callback(desktop->animation_manager, NULL); | ||||||
|  | |||||||
| @ -7,8 +7,6 @@ typedef enum { | |||||||
|     DesktopMainEventOpenMenu, |     DesktopMainEventOpenMenu, | ||||||
|     DesktopMainEventOpenDebug, |     DesktopMainEventOpenDebug, | ||||||
|     DesktopMainEventRightShort, |     DesktopMainEventRightShort, | ||||||
|     DesktopMainEventBeforeAppStarted, |  | ||||||
|     DesktopMainEventAfterAppFinished, |  | ||||||
| 
 | 
 | ||||||
|     DesktopLockedEventUnlocked, |     DesktopLockedEventUnlocked, | ||||||
|     DesktopLockedEventUpdate, |     DesktopLockedEventUpdate, | ||||||
| @ -37,4 +35,7 @@ typedef enum { | |||||||
|     DesktopAnimationEventNewIdleAnimation, |     DesktopAnimationEventNewIdleAnimation, | ||||||
|     DesktopAnimationEventInteractAnimation, |     DesktopAnimationEventInteractAnimation, | ||||||
| 
 | 
 | ||||||
|  |     // Global events
 | ||||||
|  |     DesktopGlobalBeforeAppStarted, | ||||||
|  |     DesktopGlobalAfterAppFinished, | ||||||
| } DesktopEvent; | } DesktopEvent; | ||||||
|  | |||||||
| @ -209,6 +209,7 @@ void ibutton_cli_emulate(Cli* cli, string_t args) { | |||||||
| 
 | 
 | ||||||
|     while(!exit) { |     while(!exit) { | ||||||
|         exit = cli_cmd_interrupt_received(cli); |         exit = cli_cmd_interrupt_received(cli); | ||||||
|  |         delay(100); | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     worker->stop_emulate(); |     worker->stop_emulate(); | ||||||
|  | |||||||
| @ -2,7 +2,6 @@ | |||||||
| #include <furi.h> | #include <furi.h> | ||||||
| #include <furi_hal.h> | #include <furi_hal.h> | ||||||
| #include <stm32wbxx_ll_cortex.h> | #include <stm32wbxx_ll_cortex.h> | ||||||
| #include <tim.h> |  | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * @brief private violation assistant for RfidReader |  * @brief private violation assistant for RfidReader | ||||||
|  | |||||||
| @ -1,7 +1,5 @@ | |||||||
| #include "rfid_timer_emulator.h" | #include "rfid_timer_emulator.h" | ||||||
| 
 | 
 | ||||||
| extern TIM_HandleTypeDef htim1; |  | ||||||
| 
 |  | ||||||
| RfidTimerEmulator::RfidTimerEmulator() { | RfidTimerEmulator::RfidTimerEmulator() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -25,9 +23,7 @@ void RfidTimerEmulator::start(LfrfidKeyType type, const uint8_t* data, uint8_t d | |||||||
|             furi_hal_rfid_tim_emulate(125000); |             furi_hal_rfid_tim_emulate(125000); | ||||||
|             furi_hal_rfid_pins_emulate(); |             furi_hal_rfid_pins_emulate(); | ||||||
| 
 | 
 | ||||||
|             api_interrupt_add(timer_update_callback, InterruptTypeTimerUpdate, this); |             furi_hal_rfid_tim_emulate_start(RfidTimerEmulator::timer_update_callback, this); | ||||||
| 
 |  | ||||||
|             furi_hal_rfid_tim_emulate_start(); |  | ||||||
|         } |         } | ||||||
|     } else { |     } else { | ||||||
|         // not found
 |         // not found
 | ||||||
| @ -36,17 +32,13 @@ void RfidTimerEmulator::start(LfrfidKeyType type, const uint8_t* data, uint8_t d | |||||||
| 
 | 
 | ||||||
| void RfidTimerEmulator::stop() { | void RfidTimerEmulator::stop() { | ||||||
|     furi_hal_rfid_tim_emulate_stop(); |     furi_hal_rfid_tim_emulate_stop(); | ||||||
|     api_interrupt_remove(timer_update_callback, InterruptTypeTimerUpdate); |  | ||||||
| 
 |  | ||||||
|     furi_hal_rfid_tim_reset(); |     furi_hal_rfid_tim_reset(); | ||||||
|     furi_hal_rfid_pins_reset(); |     furi_hal_rfid_pins_reset(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RfidTimerEmulator::timer_update_callback(void* _hw, void* ctx) { | void RfidTimerEmulator::timer_update_callback(void* ctx) { | ||||||
|     RfidTimerEmulator* _this = static_cast<RfidTimerEmulator*>(ctx); |     RfidTimerEmulator* _this = static_cast<RfidTimerEmulator*>(ctx); | ||||||
|     TIM_HandleTypeDef* hw = static_cast<TIM_HandleTypeDef*>(_hw); |  | ||||||
| 
 | 
 | ||||||
|     if(furi_hal_rfid_is_tim_emulate(hw)) { |  | ||||||
|     bool result; |     bool result; | ||||||
|     bool polarity; |     bool polarity; | ||||||
|     uint16_t period; |     uint16_t period; | ||||||
| @ -62,4 +54,3 @@ void RfidTimerEmulator::timer_update_callback(void* _hw, void* ctx) { | |||||||
|     furi_hal_rfid_set_emulate_period(period - 1); |     furi_hal_rfid_set_emulate_period(period - 1); | ||||||
|     furi_hal_rfid_set_emulate_pulse(pulse); |     furi_hal_rfid_set_emulate_pulse(pulse); | ||||||
| } | } | ||||||
| } |  | ||||||
|  | |||||||
| @ -25,5 +25,5 @@ private: | |||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     PulseJoiner pulse_joiner; |     PulseJoiner pulse_joiner; | ||||||
|     static void timer_update_callback(void* _hw, void* ctx); |     static void timer_update_callback(void* ctx); | ||||||
| }; | }; | ||||||
| @ -25,6 +25,10 @@ typedef enum { | |||||||
| } NfcWorkerState; | } NfcWorkerState; | ||||||
| 
 | 
 | ||||||
| typedef enum { | typedef enum { | ||||||
|  |     // Reserve first 50 events for application events
 | ||||||
|  |     NfcWorkerEventReserved = 50, | ||||||
|  | 
 | ||||||
|  |     // Nfc worker common events
 | ||||||
|     NfcWorkerEventSuccess, |     NfcWorkerEventSuccess, | ||||||
|     NfcWorkerEventFail, |     NfcWorkerEventFail, | ||||||
|     NfcWorkerEventNoCardDetected, |     NfcWorkerEventNoCardDetected, | ||||||
|  | |||||||
| @ -1,7 +1,6 @@ | |||||||
| #include "furi.h" | #include "furi.h" | ||||||
| 
 | 
 | ||||||
| void furi_init() { | void furi_init() { | ||||||
|     api_interrupt_init(); |  | ||||||
|     furi_log_init(); |     furi_log_init(); | ||||||
|     furi_record_init(); |     furi_record_init(); | ||||||
|     furi_stdglue_init(); |     furi_stdglue_init(); | ||||||
|  | |||||||
| @ -18,7 +18,6 @@ | |||||||
| #include <furi/log.h> | #include <furi/log.h> | ||||||
| 
 | 
 | ||||||
| #include <furi_hal_gpio.h> | #include <furi_hal_gpio.h> | ||||||
| #include <furi_hal/api_interrupt_mgr.h> |  | ||||||
| 
 | 
 | ||||||
| #include <stdlib.h> | #include <stdlib.h> | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,65 +0,0 @@ | |||||||
| #include "api_interrupt_mgr.h" |  | ||||||
| #include <cmsis_os2.h> |  | ||||||
| #include <furi.h> |  | ||||||
| 
 |  | ||||||
| static volatile InterruptCallbackItem callback_list[InterruptTypeLast]; |  | ||||||
| 
 |  | ||||||
| bool api_interrupt_init() { |  | ||||||
|     for(uint8_t i = 0; i < InterruptTypeLast; i++) { |  | ||||||
|         callback_list[i].callback = NULL; |  | ||||||
|         callback_list[i].context = NULL; |  | ||||||
|         callback_list[i].ready = false; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void api_interrupt_add(InterruptCallback callback, InterruptType type, void* context) { |  | ||||||
|     furi_assert(type < InterruptTypeLast); |  | ||||||
|     furi_check(callback_list[type].callback == NULL); |  | ||||||
| 
 |  | ||||||
|     callback_list[type].callback = callback; |  | ||||||
|     callback_list[type].context = context; |  | ||||||
|     __DMB(); |  | ||||||
|     callback_list[type].ready = true; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void api_interrupt_remove(InterruptCallback callback, InterruptType type) { |  | ||||||
|     furi_assert(type < InterruptTypeLast); |  | ||||||
|     if(callback_list[type].callback != NULL) { |  | ||||||
|         furi_check(callback_list[type].callback == callback); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     callback_list[type].ready = false; |  | ||||||
|     __DMB(); |  | ||||||
|     callback_list[type].callback = NULL; |  | ||||||
|     callback_list[type].context = NULL; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void api_interrupt_enable(InterruptCallback callback, InterruptType type) { |  | ||||||
|     furi_assert(type < InterruptTypeLast); |  | ||||||
|     furi_check(callback_list[type].callback == callback); |  | ||||||
| 
 |  | ||||||
|     callback_list[type].ready = true; |  | ||||||
|     __DMB(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void api_interrupt_disable(InterruptCallback callback, InterruptType type) { |  | ||||||
|     furi_assert(type < InterruptTypeLast); |  | ||||||
|     furi_check(callback_list[type].callback == callback); |  | ||||||
| 
 |  | ||||||
|     callback_list[type].ready = false; |  | ||||||
|     __DMB(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void api_interrupt_call(InterruptType type, void* hw) { |  | ||||||
|     // that executed in interrupt ctx so mutex don't needed
 |  | ||||||
|     // but we need to check ready flag
 |  | ||||||
|     furi_assert(type < InterruptTypeLast); |  | ||||||
| 
 |  | ||||||
|     if(callback_list[type].callback != NULL) { |  | ||||||
|         if(callback_list[type].ready) { |  | ||||||
|             callback_list[type].callback(hw, callback_list[type].context); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,74 +0,0 @@ | |||||||
| /**
 |  | ||||||
|  * @file api_interrupt_mgr.h |  | ||||||
|  * Furi: interrupt API |  | ||||||
|  */ |  | ||||||
| 
 |  | ||||||
| #pragma once |  | ||||||
| 
 |  | ||||||
| #include <stdbool.h> |  | ||||||
| 
 |  | ||||||
| #ifdef __cplusplus |  | ||||||
| extern "C" { |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| /** Interrupt callback prototype */ |  | ||||||
| typedef void (*InterruptCallback)(void*, void*); |  | ||||||
| 
 |  | ||||||
| /** Interupt type */ |  | ||||||
| typedef enum { |  | ||||||
|     InterruptTypeTimerUpdate, |  | ||||||
|     InterruptTypeLast, |  | ||||||
| } InterruptType; |  | ||||||
| 
 |  | ||||||
| /** Interrupt callback type */ |  | ||||||
| typedef struct { |  | ||||||
|     InterruptCallback callback; |  | ||||||
|     void* context; |  | ||||||
|     bool ready; |  | ||||||
| } InterruptCallbackItem; |  | ||||||
| 
 |  | ||||||
| /** Init interrupt
 |  | ||||||
|  * |  | ||||||
|  * @return     true on succsessful initialization, false otherwise |  | ||||||
|  */ |  | ||||||
| bool api_interrupt_init(); |  | ||||||
| 
 |  | ||||||
| /** Add interrupt
 |  | ||||||
|  * |  | ||||||
|  * @param      callback  InterruptCallback |  | ||||||
|  * @param      type      InterruptType |  | ||||||
|  * @param      context   context for callback |  | ||||||
|  */ |  | ||||||
| void api_interrupt_add(InterruptCallback callback, InterruptType type, void* context); |  | ||||||
| 
 |  | ||||||
| /** Remove interrupt
 |  | ||||||
|  * |  | ||||||
|  * @param      callback  InterruptCallback |  | ||||||
|  * @param      type      InterruptType |  | ||||||
|  */ |  | ||||||
| void api_interrupt_remove(InterruptCallback callback, InterruptType type); |  | ||||||
| 
 |  | ||||||
| /** Enable interrupt
 |  | ||||||
|  * |  | ||||||
|  * @param      callback  InterruptCallback |  | ||||||
|  * @param      type      InterruptType |  | ||||||
|  */ |  | ||||||
| void api_interrupt_enable(InterruptCallback callback, InterruptType type); |  | ||||||
| 
 |  | ||||||
| /** Disable interrupt
 |  | ||||||
|  * |  | ||||||
|  * @param      callback  InterruptCallback |  | ||||||
|  * @param      type      InterruptType |  | ||||||
|  */ |  | ||||||
| void api_interrupt_disable(InterruptCallback callback, InterruptType type); |  | ||||||
| 
 |  | ||||||
| /** Call interrupt
 |  | ||||||
|  * |  | ||||||
|  * @param      type  InterruptType |  | ||||||
|  * @param      hw    pointer to hardware peripheral |  | ||||||
|  */ |  | ||||||
| void api_interrupt_call(InterruptType type, void* hw); |  | ||||||
| 
 |  | ||||||
| #ifdef __cplusplus |  | ||||||
| } |  | ||||||
| #endif |  | ||||||
| @ -53,7 +53,7 @@ extern "C" { | |||||||
| /*#define HAL_SMBUS_MODULE_ENABLED  */ | /*#define HAL_SMBUS_MODULE_ENABLED  */ | ||||||
| /*#define HAL_SMARTCARD_MODULE_ENABLED   */ | /*#define HAL_SMARTCARD_MODULE_ENABLED   */ | ||||||
| /*#define HAL_SPI_MODULE_ENABLED    */ | /*#define HAL_SPI_MODULE_ENABLED    */ | ||||||
| #define HAL_TIM_MODULE_ENABLED | /*#define HAL_TIM_MODULE_ENABLED    */ | ||||||
| /*#define HAL_TSC_MODULE_ENABLED    */ | /*#define HAL_TSC_MODULE_ENABLED    */ | ||||||
| /*#define HAL_UART_MODULE_ENABLED   */ | /*#define HAL_UART_MODULE_ENABLED   */ | ||||||
| /*#define HAL_USART_MODULE_ENABLED  */ | /*#define HAL_USART_MODULE_ENABLED  */ | ||||||
|  | |||||||
| @ -1,56 +0,0 @@ | |||||||
| /**
 |  | ||||||
|   ****************************************************************************** |  | ||||||
|   * @file    tim.h |  | ||||||
|   * @brief   This file contains all the function prototypes for |  | ||||||
|   *          the tim.c file |  | ||||||
|   ****************************************************************************** |  | ||||||
|   * @attention |  | ||||||
|   * |  | ||||||
|   * <h2><center>© Copyright (c) 2021 STMicroelectronics. |  | ||||||
|   * All rights reserved.</center></h2> |  | ||||||
|   * |  | ||||||
|   * This software component is licensed by ST under Ultimate Liberty license |  | ||||||
|   * SLA0044, the "License"; You may not use this file except in compliance with |  | ||||||
|   * the License. You may obtain a copy of the License at: |  | ||||||
|   *                             www.st.com/SLA0044 |  | ||||||
|   * |  | ||||||
|   ****************************************************************************** |  | ||||||
|   */ |  | ||||||
| /* Define to prevent recursive inclusion -------------------------------------*/ |  | ||||||
| #ifndef __TIM_H__ |  | ||||||
| #define __TIM_H__ |  | ||||||
| 
 |  | ||||||
| #ifdef __cplusplus |  | ||||||
| extern "C" { |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| /* Includes ------------------------------------------------------------------*/ |  | ||||||
| #include "main.h" |  | ||||||
| 
 |  | ||||||
| /* USER CODE BEGIN Includes */ |  | ||||||
| 
 |  | ||||||
| /* USER CODE END Includes */ |  | ||||||
| 
 |  | ||||||
| extern TIM_HandleTypeDef htim1; |  | ||||||
| extern TIM_HandleTypeDef htim2; |  | ||||||
| 
 |  | ||||||
| /* USER CODE BEGIN Private defines */ |  | ||||||
| 
 |  | ||||||
| /* USER CODE END Private defines */ |  | ||||||
| 
 |  | ||||||
| void MX_TIM1_Init(void); |  | ||||||
| void MX_TIM2_Init(void); |  | ||||||
| 
 |  | ||||||
| void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim); |  | ||||||
| 
 |  | ||||||
| /* USER CODE BEGIN Prototypes */ |  | ||||||
| 
 |  | ||||||
| /* USER CODE END Prototypes */ |  | ||||||
| 
 |  | ||||||
| #ifdef __cplusplus |  | ||||||
| } |  | ||||||
| #endif |  | ||||||
| 
 |  | ||||||
| #endif /* __TIM_H__ */ |  | ||||||
| 
 |  | ||||||
| /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |  | ||||||
| @ -5,7 +5,6 @@ | |||||||
| #include "usbd_core.h" | #include "usbd_core.h" | ||||||
| 
 | 
 | ||||||
| extern usbd_device udev; | extern usbd_device udev; | ||||||
| extern TIM_HandleTypeDef htim1; |  | ||||||
| 
 | 
 | ||||||
| extern void HW_TS_RTC_Wakeup_Handler(); | extern void HW_TS_RTC_Wakeup_Handler(); | ||||||
| extern void HW_IPCC_Tx_Handler(); | extern void HW_IPCC_Tx_Handler(); | ||||||
| @ -19,14 +18,6 @@ void USB_LP_IRQHandler(void) { | |||||||
|     usbd_poll(&udev); |     usbd_poll(&udev); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void TIM1_TRG_COM_TIM17_IRQHandler(void) { |  | ||||||
|     HAL_TIM_IRQHandler(&htim1); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void TIM1_CC_IRQHandler(void) { |  | ||||||
|     HAL_TIM_IRQHandler(&htim1); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void HSEM_IRQHandler(void) { | void HSEM_IRQHandler(void) { | ||||||
|     HAL_HSEM_IRQHandler(); |     HAL_HSEM_IRQHandler(); | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,150 +0,0 @@ | |||||||
| #include "tim.h" |  | ||||||
| 
 |  | ||||||
| TIM_HandleTypeDef htim1; |  | ||||||
| TIM_HandleTypeDef htim2; |  | ||||||
| 
 |  | ||||||
| /* TIM1 init function */ |  | ||||||
| void MX_TIM1_Init(void) { |  | ||||||
|     TIM_ClockConfigTypeDef sClockSourceConfig = {0}; |  | ||||||
|     TIM_MasterConfigTypeDef sMasterConfig = {0}; |  | ||||||
|     TIM_OC_InitTypeDef sConfigOC = {0}; |  | ||||||
|     TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0}; |  | ||||||
| 
 |  | ||||||
|     htim1.Instance = TIM1; |  | ||||||
|     htim1.Init.Prescaler = 0; |  | ||||||
|     htim1.Init.CounterMode = TIM_COUNTERMODE_UP; |  | ||||||
|     htim1.Init.Period = 65535; |  | ||||||
|     htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; |  | ||||||
|     htim1.Init.RepetitionCounter = 0; |  | ||||||
|     htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; |  | ||||||
|     if(HAL_TIM_Base_Init(&htim1) != HAL_OK) { |  | ||||||
|         Error_Handler(); |  | ||||||
|     } |  | ||||||
|     sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; |  | ||||||
|     if(HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK) { |  | ||||||
|         Error_Handler(); |  | ||||||
|     } |  | ||||||
|     if(HAL_TIM_OC_Init(&htim1) != HAL_OK) { |  | ||||||
|         Error_Handler(); |  | ||||||
|     } |  | ||||||
|     if(HAL_TIM_PWM_Init(&htim1) != HAL_OK) { |  | ||||||
|         Error_Handler(); |  | ||||||
|     } |  | ||||||
|     sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; |  | ||||||
|     sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET; |  | ||||||
|     sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; |  | ||||||
|     if(HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK) { |  | ||||||
|         Error_Handler(); |  | ||||||
|     } |  | ||||||
|     sConfigOC.OCMode = TIM_OCMODE_TIMING; |  | ||||||
|     sConfigOC.Pulse = 0; |  | ||||||
|     sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; |  | ||||||
|     sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; |  | ||||||
|     sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; |  | ||||||
|     sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; |  | ||||||
|     sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; |  | ||||||
|     if(HAL_TIM_OC_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK) { |  | ||||||
|         Error_Handler(); |  | ||||||
|     } |  | ||||||
|     sConfigOC.OCMode = TIM_OCMODE_PWM1; |  | ||||||
|     if(HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_3) != HAL_OK) { |  | ||||||
|         Error_Handler(); |  | ||||||
|     } |  | ||||||
|     sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE; |  | ||||||
|     sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE; |  | ||||||
|     sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF; |  | ||||||
|     sBreakDeadTimeConfig.DeadTime = 0; |  | ||||||
|     sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE; |  | ||||||
|     sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH; |  | ||||||
|     sBreakDeadTimeConfig.BreakFilter = 0; |  | ||||||
|     sBreakDeadTimeConfig.BreakAFMode = TIM_BREAK_AFMODE_INPUT; |  | ||||||
|     sBreakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE; |  | ||||||
|     sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH; |  | ||||||
|     sBreakDeadTimeConfig.Break2Filter = 0; |  | ||||||
|     sBreakDeadTimeConfig.Break2AFMode = TIM_BREAK_AFMODE_INPUT; |  | ||||||
|     sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE; |  | ||||||
|     if(HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK) { |  | ||||||
|         Error_Handler(); |  | ||||||
|     } |  | ||||||
|     HAL_TIM_MspPostInit(&htim1); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* TIM2 init function */ |  | ||||||
| void MX_TIM2_Init(void) { |  | ||||||
|     TIM_ClockConfigTypeDef sClockSourceConfig = {0}; |  | ||||||
|     TIM_MasterConfigTypeDef sMasterConfig = {0}; |  | ||||||
|     TIM_IC_InitTypeDef sConfigIC = {0}; |  | ||||||
| 
 |  | ||||||
|     htim2.Instance = TIM2; |  | ||||||
|     htim2.Init.Prescaler = 64 - 1; |  | ||||||
|     htim2.Init.CounterMode = TIM_COUNTERMODE_UP; |  | ||||||
|     htim2.Init.Period = 4294967295; |  | ||||||
|     htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; |  | ||||||
|     htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; |  | ||||||
|     if(HAL_TIM_Base_Init(&htim2) != HAL_OK) { |  | ||||||
|         Error_Handler(); |  | ||||||
|     } |  | ||||||
|     sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; |  | ||||||
|     if(HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK) { |  | ||||||
|         Error_Handler(); |  | ||||||
|     } |  | ||||||
|     if(HAL_TIM_IC_Init(&htim2) != HAL_OK) { |  | ||||||
|         Error_Handler(); |  | ||||||
|     } |  | ||||||
|     sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; |  | ||||||
|     sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; |  | ||||||
|     if(HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK) { |  | ||||||
|         Error_Handler(); |  | ||||||
|     } |  | ||||||
|     sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING; |  | ||||||
|     sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI; |  | ||||||
|     sConfigIC.ICPrescaler = TIM_ICPSC_DIV1; |  | ||||||
|     sConfigIC.ICFilter = 0; |  | ||||||
|     if(HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_1) != HAL_OK) { |  | ||||||
|         Error_Handler(); |  | ||||||
|     } |  | ||||||
|     sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING; |  | ||||||
|     sConfigIC.ICSelection = TIM_ICSELECTION_INDIRECTTI; |  | ||||||
|     if(HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_2) != HAL_OK) { |  | ||||||
|         Error_Handler(); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* tim_baseHandle) { |  | ||||||
|     GPIO_InitTypeDef GPIO_InitStruct = {0}; |  | ||||||
|     if(tim_baseHandle->Instance == TIM1) { |  | ||||||
|         HAL_NVIC_SetPriority(TIM1_TRG_COM_TIM17_IRQn, 0, 0); |  | ||||||
|         HAL_NVIC_EnableIRQ(TIM1_TRG_COM_TIM17_IRQn); |  | ||||||
|     } else if(tim_baseHandle->Instance == TIM2) { |  | ||||||
|         GPIO_InitStruct.Pin = IR_RX_Pin; |  | ||||||
|         GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; |  | ||||||
|         GPIO_InitStruct.Pull = GPIO_NOPULL; |  | ||||||
|         GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; |  | ||||||
|         GPIO_InitStruct.Alternate = GPIO_AF1_TIM2; |  | ||||||
|         HAL_GPIO_Init(IR_RX_GPIO_Port, &GPIO_InitStruct); |  | ||||||
| 
 |  | ||||||
|         /* TIM2 interrupt Init */ |  | ||||||
|         HAL_NVIC_SetPriority(TIM2_IRQn, 5, 0); |  | ||||||
|         HAL_NVIC_EnableIRQ(TIM2_IRQn); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| void HAL_TIM_MspPostInit(TIM_HandleTypeDef* timHandle) { |  | ||||||
|     GPIO_InitTypeDef GPIO_InitStruct = {0}; |  | ||||||
|     if(timHandle->Instance == TIM1) { |  | ||||||
|         GPIO_InitStruct.Pin = IR_TX_Pin | RFID_OUT_Pin; |  | ||||||
|         GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; |  | ||||||
|         GPIO_InitStruct.Pull = GPIO_NOPULL; |  | ||||||
|         GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; |  | ||||||
|         GPIO_InitStruct.Alternate = GPIO_AF1_TIM1; |  | ||||||
|         HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* tim_baseHandle) { |  | ||||||
|     if(tim_baseHandle->Instance == TIM1) { |  | ||||||
|         HAL_NVIC_DisableIRQ(TIM1_TRG_COM_TIM17_IRQn); |  | ||||||
|     } else if(tim_baseHandle->Instance == TIM2) { |  | ||||||
|         HAL_GPIO_DeInit(IR_RX_GPIO_Port, IR_RX_Pin); |  | ||||||
|         HAL_NVIC_DisableIRQ(TIM2_IRQn); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @ -1,6 +1,5 @@ | |||||||
| #include <furi_hal.h> | #include <furi_hal.h> | ||||||
| 
 | 
 | ||||||
| #include <tim.h> |  | ||||||
| #include <gpio.h> | #include <gpio.h> | ||||||
| 
 | 
 | ||||||
| #include <stm32wbxx_ll_cortex.h> | #include <stm32wbxx_ll_cortex.h> | ||||||
| @ -22,11 +21,6 @@ void furi_hal_init() { | |||||||
| 
 | 
 | ||||||
|     furi_hal_spi_init(); |     furi_hal_spi_init(); | ||||||
| 
 | 
 | ||||||
|     MX_TIM1_Init(); |  | ||||||
|     FURI_LOG_I(TAG, "TIM1 OK"); |  | ||||||
|     MX_TIM2_Init(); |  | ||||||
|     FURI_LOG_I(TAG, "TIM2 OK"); |  | ||||||
| 
 |  | ||||||
|     furi_hal_ibutton_init(); |     furi_hal_ibutton_init(); | ||||||
|     FURI_LOG_I(TAG, "iButton OK"); |     FURI_LOG_I(TAG, "iButton OK"); | ||||||
|     furi_hal_speaker_init(); |     furi_hal_speaker_init(); | ||||||
|  | |||||||
| @ -49,6 +49,11 @@ void furi_hal_ibutton_emulate_start( | |||||||
|     LL_TIM_DeInit(FURI_HAL_IBUTTON_TIMER); |     LL_TIM_DeInit(FURI_HAL_IBUTTON_TIMER); | ||||||
|     FURI_CRITICAL_EXIT(); |     FURI_CRITICAL_EXIT(); | ||||||
| 
 | 
 | ||||||
|  |     furi_hal_interrupt_set_timer_isr(FURI_HAL_IBUTTON_TIMER, furi_hal_ibutton_emulate_isr); | ||||||
|  |     NVIC_SetPriority( | ||||||
|  |         FURI_HAL_IBUTTON_TIMER_IRQ, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0)); | ||||||
|  |     NVIC_EnableIRQ(FURI_HAL_IBUTTON_TIMER_IRQ); | ||||||
|  | 
 | ||||||
|     LL_TIM_SetPrescaler(FURI_HAL_IBUTTON_TIMER, 0); |     LL_TIM_SetPrescaler(FURI_HAL_IBUTTON_TIMER, 0); | ||||||
|     LL_TIM_SetCounterMode(FURI_HAL_IBUTTON_TIMER, LL_TIM_COUNTERMODE_UP); |     LL_TIM_SetCounterMode(FURI_HAL_IBUTTON_TIMER, LL_TIM_COUNTERMODE_UP); | ||||||
|     LL_TIM_SetAutoReload(FURI_HAL_IBUTTON_TIMER, period); |     LL_TIM_SetAutoReload(FURI_HAL_IBUTTON_TIMER, period); | ||||||
| @ -61,12 +66,6 @@ void furi_hal_ibutton_emulate_start( | |||||||
| 
 | 
 | ||||||
|     LL_TIM_EnableIT_UPDATE(FURI_HAL_IBUTTON_TIMER); |     LL_TIM_EnableIT_UPDATE(FURI_HAL_IBUTTON_TIMER); | ||||||
| 
 | 
 | ||||||
|     furi_hal_interrupt_set_timer_isr(FURI_HAL_IBUTTON_TIMER, furi_hal_ibutton_emulate_isr); |  | ||||||
| 
 |  | ||||||
|     NVIC_SetPriority( |  | ||||||
|         FURI_HAL_IBUTTON_TIMER_IRQ, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0)); |  | ||||||
|     NVIC_EnableIRQ(FURI_HAL_IBUTTON_TIMER_IRQ); |  | ||||||
| 
 |  | ||||||
|     LL_TIM_EnableCounter(FURI_HAL_IBUTTON_TIMER); |     LL_TIM_EnableCounter(FURI_HAL_IBUTTON_TIMER); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -80,6 +79,11 @@ void furi_hal_ibutton_emulate_stop() { | |||||||
|     if(furi_hal_ibutton->state == FuriHalIbuttonStateRunning) { |     if(furi_hal_ibutton->state == FuriHalIbuttonStateRunning) { | ||||||
|         furi_hal_ibutton->state = FuriHalIbuttonStateIdle; |         furi_hal_ibutton->state = FuriHalIbuttonStateIdle; | ||||||
|         LL_TIM_DisableCounter(FURI_HAL_IBUTTON_TIMER); |         LL_TIM_DisableCounter(FURI_HAL_IBUTTON_TIMER); | ||||||
|  | 
 | ||||||
|  |         FURI_CRITICAL_ENTER(); | ||||||
|  |         LL_TIM_DeInit(FURI_HAL_IBUTTON_TIMER); | ||||||
|  |         FURI_CRITICAL_EXIT(); | ||||||
|  | 
 | ||||||
|         furi_hal_interrupt_set_timer_isr(FURI_HAL_IBUTTON_TIMER, NULL); |         furi_hal_interrupt_set_timer_isr(FURI_HAL_IBUTTON_TIMER, NULL); | ||||||
| 
 | 
 | ||||||
|         furi_hal_ibutton->callback = NULL; |         furi_hal_ibutton->callback = NULL; | ||||||
|  | |||||||
| @ -3,7 +3,6 @@ | |||||||
| #include <furi.h> | #include <furi.h> | ||||||
| #include <main.h> | #include <main.h> | ||||||
| 
 | 
 | ||||||
| #include <tim.h> |  | ||||||
| #include <stm32wbxx_ll_tim.h> | #include <stm32wbxx_ll_tim.h> | ||||||
| 
 | 
 | ||||||
| #define TAG "FuriHalInterrupt" | #define TAG "FuriHalInterrupt" | ||||||
| @ -67,20 +66,10 @@ void furi_hal_interrupt_set_dma_channel_isr( | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| extern void api_interrupt_call(InterruptType type, void* hw); |  | ||||||
| 
 |  | ||||||
| /* ST HAL symbols */ |  | ||||||
| /* Timer update event */ |  | ||||||
| void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim) { |  | ||||||
|     api_interrupt_call(InterruptTypeTimerUpdate, htim); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| /* Timer 2 */ | /* Timer 2 */ | ||||||
| void TIM2_IRQHandler(void) { | void TIM2_IRQHandler(void) { | ||||||
|     if(furi_hal_tim_tim2_isr) { |     if(furi_hal_tim_tim2_isr) { | ||||||
|         furi_hal_tim_tim2_isr(); |         furi_hal_tim_tim2_isr(); | ||||||
|     } else { |  | ||||||
|         HAL_TIM_IRQHandler(&htim2); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -88,11 +77,15 @@ void TIM2_IRQHandler(void) { | |||||||
| void TIM1_UP_TIM16_IRQHandler(void) { | void TIM1_UP_TIM16_IRQHandler(void) { | ||||||
|     if(furi_hal_tim_tim1_isr) { |     if(furi_hal_tim_tim1_isr) { | ||||||
|         furi_hal_tim_tim1_isr(); |         furi_hal_tim_tim1_isr(); | ||||||
|     } else { |  | ||||||
|         HAL_TIM_IRQHandler(&htim1); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void TIM1_TRG_COM_TIM17_IRQHandler(void) { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void TIM1_CC_IRQHandler(void) { | ||||||
|  | } | ||||||
|  | 
 | ||||||
| /* DMA 1 */ | /* DMA 1 */ | ||||||
| void DMA1_Channel1_IRQHandler(void) { | void DMA1_Channel1_IRQHandler(void) { | ||||||
|     if(furi_hal_dma_channel_isr[0][0]) furi_hal_dma_channel_isr[0][0](); |     if(furi_hal_dma_channel_isr[0][0]) furi_hal_dma_channel_isr[0][0](); | ||||||
|  | |||||||
| @ -1,20 +1,32 @@ | |||||||
| #include <furi_hal_rfid.h> | #include <furi_hal_rfid.h> | ||||||
| #include <furi_hal_ibutton.h> | #include <furi_hal_ibutton.h> | ||||||
|  | #include <furi_hal_interrupt.h> | ||||||
| #include <furi_hal_resources.h> | #include <furi_hal_resources.h> | ||||||
| #include <furi_hal_version.h> | #include <furi.h> | ||||||
| 
 | 
 | ||||||
| #include <tim.h> |  | ||||||
| #include <stm32wbxx_ll_tim.h> | #include <stm32wbxx_ll_tim.h> | ||||||
| #include <stm32wbxx_ll_comp.h> | #include <stm32wbxx_ll_comp.h> | ||||||
| 
 | 
 | ||||||
| #define LFRFID_TIM htim1 | #define FURI_HAL_RFID_READ_TIMER TIM1 | ||||||
| #define LFRFID_CH TIM_CHANNEL_1 | #define FURI_HAL_RFID_READ_TIMER_CHANNEL LL_TIM_CHANNEL_CH1N | ||||||
| #define LFRFID_READ_TIM htim1 | // We can't use N channel for LL_TIM_OC_Init, so...
 | ||||||
| #define LFRFID_READ_CHANNEL TIM_CHANNEL_1 | #define FURI_HAL_RFID_READ_TIMER_CHANNEL_CONFIG LL_TIM_CHANNEL_CH1 | ||||||
| #define LFRFID_EMULATE_TIM htim2 | 
 | ||||||
| #define LFRFID_EMULATE_CHANNEL TIM_CHANNEL_3 | #define FURI_HAL_RFID_EMULATE_TIMER TIM2 | ||||||
|  | #define FURI_HAL_RFID_EMULATE_TIMER_IRQ TIM2_IRQn | ||||||
|  | #define FURI_HAL_RFID_EMULATE_TIMER_CHANNEL LL_TIM_CHANNEL_CH3 | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  |     FuriHalRfidEmulateCallback callback; | ||||||
|  |     void* context; | ||||||
|  | } FuriHalRfid; | ||||||
|  | 
 | ||||||
|  | FuriHalRfid* furi_hal_rfid = NULL; | ||||||
| 
 | 
 | ||||||
| void furi_hal_rfid_init() { | void furi_hal_rfid_init() { | ||||||
|  |     furi_assert(furi_hal_rfid == NULL); | ||||||
|  |     furi_hal_rfid = malloc(sizeof(FuriHalRfid)); | ||||||
|  | 
 | ||||||
|     furi_hal_rfid_pins_reset(); |     furi_hal_rfid_pins_reset(); | ||||||
| 
 | 
 | ||||||
|     LL_COMP_InitTypeDef COMP_InitStruct = {0}; |     LL_COMP_InitTypeDef COMP_InitStruct = {0}; | ||||||
| @ -105,210 +117,128 @@ void furi_hal_rfid_pin_pull_pulldown() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_rfid_tim_read(float freq, float duty_cycle) { | void furi_hal_rfid_tim_read(float freq, float duty_cycle) { | ||||||
|     // TODO LL init
 |     FURI_CRITICAL_ENTER(); | ||||||
|     uint32_t period = (uint32_t)((SystemCoreClock) / freq) - 1; |     LL_TIM_DeInit(FURI_HAL_RFID_READ_TIMER); | ||||||
|  |     FURI_CRITICAL_EXIT(); | ||||||
| 
 | 
 | ||||||
|     TIM_ClockConfigTypeDef sClockSourceConfig = {0}; |     LL_TIM_InitTypeDef TIM_InitStruct = {0}; | ||||||
|     TIM_MasterConfigTypeDef sMasterConfig = {0}; |     TIM_InitStruct.Autoreload = (SystemCoreClock / freq) - 1; | ||||||
|     TIM_OC_InitTypeDef sConfigOC = {0}; |     LL_TIM_Init(FURI_HAL_RFID_READ_TIMER, &TIM_InitStruct); | ||||||
|     TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0}; |     LL_TIM_DisableARRPreload(FURI_HAL_RFID_READ_TIMER); | ||||||
| 
 | 
 | ||||||
|     // basic PWM setup with needed freq and internal clock
 |     LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0}; | ||||||
|     LFRFID_READ_TIM.Init.Prescaler = 0; |     TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1; | ||||||
|     LFRFID_READ_TIM.Init.CounterMode = TIM_COUNTERMODE_UP; |     TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_ENABLE; | ||||||
|     LFRFID_READ_TIM.Init.Period = period; |     TIM_OC_InitStruct.CompareValue = TIM_InitStruct.Autoreload * duty_cycle; | ||||||
|     LFRFID_READ_TIM.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; |     LL_TIM_OC_Init( | ||||||
|     LFRFID_READ_TIM.Init.RepetitionCounter = 0; |         FURI_HAL_RFID_READ_TIMER, FURI_HAL_RFID_READ_TIMER_CHANNEL_CONFIG, &TIM_OC_InitStruct); | ||||||
|     LFRFID_READ_TIM.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE; |  | ||||||
|     if(HAL_TIM_Base_Init(&LFRFID_READ_TIM) != HAL_OK) { |  | ||||||
|         Error_Handler(); |  | ||||||
|     } |  | ||||||
|     sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; |  | ||||||
|     if(HAL_TIM_ConfigClockSource(&LFRFID_READ_TIM, &sClockSourceConfig) != HAL_OK) { |  | ||||||
|         Error_Handler(); |  | ||||||
|     } |  | ||||||
|     if(HAL_TIM_PWM_Init(&LFRFID_READ_TIM) != HAL_OK) { |  | ||||||
|         Error_Handler(); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     // no master-slave mode
 |     LL_TIM_EnableCounter(FURI_HAL_RFID_READ_TIMER); | ||||||
|     sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; |  | ||||||
|     sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET; |  | ||||||
|     sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; |  | ||||||
|     if(HAL_TIMEx_MasterConfigSynchronization(&LFRFID_READ_TIM, &sMasterConfig) != HAL_OK) { |  | ||||||
|         Error_Handler(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // pwm config
 |  | ||||||
|     sConfigOC.OCMode = TIM_OCMODE_PWM1; |  | ||||||
|     sConfigOC.Pulse = (uint32_t)(LFRFID_READ_TIM.Init.Period * duty_cycle); |  | ||||||
|     sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; |  | ||||||
|     sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; |  | ||||||
|     sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; |  | ||||||
|     sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; |  | ||||||
|     sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; |  | ||||||
|     if(HAL_TIM_PWM_ConfigChannel(&LFRFID_READ_TIM, &sConfigOC, LFRFID_READ_CHANNEL) != HAL_OK) { |  | ||||||
|         Error_Handler(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // no deadtime
 |  | ||||||
|     sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE; |  | ||||||
|     sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE; |  | ||||||
|     sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF; |  | ||||||
|     sBreakDeadTimeConfig.DeadTime = 0; |  | ||||||
|     sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE; |  | ||||||
|     sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH; |  | ||||||
|     sBreakDeadTimeConfig.BreakFilter = 0; |  | ||||||
|     sBreakDeadTimeConfig.BreakAFMode = TIM_BREAK_AFMODE_INPUT; |  | ||||||
|     sBreakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE; |  | ||||||
|     sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH; |  | ||||||
|     sBreakDeadTimeConfig.Break2Filter = 0; |  | ||||||
|     sBreakDeadTimeConfig.Break2AFMode = TIM_BREAK_AFMODE_INPUT; |  | ||||||
|     sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE; |  | ||||||
|     if(HAL_TIMEx_ConfigBreakDeadTime(&LFRFID_READ_TIM, &sBreakDeadTimeConfig) != HAL_OK) { |  | ||||||
|         Error_Handler(); |  | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_rfid_tim_read_start() { | void furi_hal_rfid_tim_read_start() { | ||||||
|     HAL_TIMEx_PWMN_Start(&LFRFID_READ_TIM, LFRFID_READ_CHANNEL); |     LL_TIM_EnableAllOutputs(FURI_HAL_RFID_READ_TIMER); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_rfid_tim_read_stop() { | void furi_hal_rfid_tim_read_stop() { | ||||||
|     HAL_TIMEx_PWMN_Stop(&LFRFID_READ_TIM, LFRFID_READ_CHANNEL); |     LL_TIM_DisableAllOutputs(FURI_HAL_RFID_READ_TIMER); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_rfid_tim_emulate(float freq) { | void furi_hal_rfid_tim_emulate(float freq) { | ||||||
|     // TODO LL init
 |  | ||||||
|     // uint32_t prescaler = (uint32_t)((SystemCoreClock) / freq) - 1;
 |  | ||||||
| 
 |  | ||||||
|     TIM_ClockConfigTypeDef sClockSourceConfig = {0}; |  | ||||||
|     TIM_MasterConfigTypeDef sMasterConfig = {0}; |  | ||||||
|     TIM_OC_InitTypeDef sConfigOC = {0}; |  | ||||||
| 
 |  | ||||||
|     // basic PWM setup with needed freq and internal clock
 |     // basic PWM setup with needed freq and internal clock
 | ||||||
|     LFRFID_EMULATE_TIM.Init.Prescaler = 0; |     FURI_CRITICAL_ENTER(); | ||||||
|     LFRFID_EMULATE_TIM.Init.CounterMode = TIM_COUNTERMODE_UP; |     LL_TIM_DeInit(FURI_HAL_RFID_EMULATE_TIMER); | ||||||
|     LFRFID_EMULATE_TIM.Init.Period = 1; |     FURI_CRITICAL_EXIT(); | ||||||
|     LFRFID_EMULATE_TIM.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; | 
 | ||||||
|     LFRFID_EMULATE_TIM.Init.RepetitionCounter = 0; |     LL_TIM_SetPrescaler(FURI_HAL_RFID_EMULATE_TIMER, 0); | ||||||
|     LFRFID_EMULATE_TIM.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; |     LL_TIM_SetCounterMode(FURI_HAL_RFID_EMULATE_TIMER, LL_TIM_COUNTERMODE_UP); | ||||||
|     if(HAL_TIM_Base_Init(&LFRFID_EMULATE_TIM) != HAL_OK) { |     LL_TIM_SetAutoReload(FURI_HAL_RFID_EMULATE_TIMER, 1); | ||||||
|         Error_Handler(); |     LL_TIM_DisableARRPreload(FURI_HAL_RFID_EMULATE_TIMER); | ||||||
|  |     LL_TIM_SetRepetitionCounter(FURI_HAL_RFID_EMULATE_TIMER, 0); | ||||||
|  | 
 | ||||||
|  |     LL_TIM_SetClockDivision(FURI_HAL_RFID_EMULATE_TIMER, LL_TIM_CLOCKDIVISION_DIV1); | ||||||
|  |     LL_TIM_SetClockSource(FURI_HAL_RFID_EMULATE_TIMER, LL_TIM_CLOCKSOURCE_EXT_MODE2); | ||||||
|  |     LL_TIM_ConfigETR( | ||||||
|  |         FURI_HAL_RFID_EMULATE_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_EMULATE_TIMER, FURI_HAL_RFID_EMULATE_TIMER_CHANNEL, &TIM_OC_InitStruct); | ||||||
|  | 
 | ||||||
|  |     LL_TIM_GenerateEvent_UPDATE(FURI_HAL_RFID_EMULATE_TIMER); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|     sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_ETRMODE2; | static void furi_hal_rfid_emulate_isr() { | ||||||
|     sClockSourceConfig.ClockPolarity = TIM_ETRPOLARITY_INVERTED; |     if(LL_TIM_IsActiveFlag_UPDATE(FURI_HAL_RFID_EMULATE_TIMER)) { | ||||||
|     sClockSourceConfig.ClockPrescaler = TIM_CLOCKPRESCALER_DIV1; |         LL_TIM_ClearFlag_UPDATE(FURI_HAL_RFID_EMULATE_TIMER); | ||||||
|     sClockSourceConfig.ClockFilter = 0; |         furi_hal_rfid->callback(furi_hal_rfid->context); | ||||||
|     if(HAL_TIM_ConfigClockSource(&LFRFID_EMULATE_TIM, &sClockSourceConfig) != HAL_OK) { |  | ||||||
|         Error_Handler(); |  | ||||||
|     } |  | ||||||
|     if(HAL_TIM_PWM_Init(&LFRFID_EMULATE_TIM) != HAL_OK) { |  | ||||||
|         Error_Handler(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // no master-slave mode
 |  | ||||||
|     sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; |  | ||||||
|     sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET; |  | ||||||
|     sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; |  | ||||||
|     if(HAL_TIMEx_MasterConfigSynchronization(&LFRFID_EMULATE_TIM, &sMasterConfig) != HAL_OK) { |  | ||||||
|         Error_Handler(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     // pwm config
 |  | ||||||
|     sConfigOC.OCMode = TIM_OCMODE_PWM1; |  | ||||||
|     sConfigOC.Pulse = 1; |  | ||||||
|     sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; |  | ||||||
|     sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH; |  | ||||||
|     sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; |  | ||||||
|     sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET; |  | ||||||
|     sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET; |  | ||||||
|     if(HAL_TIM_PWM_ConfigChannel(&LFRFID_EMULATE_TIM, &sConfigOC, LFRFID_EMULATE_CHANNEL) != |  | ||||||
|        HAL_OK) { |  | ||||||
|         Error_Handler(); |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_rfid_tim_emulate_start() { | void furi_hal_rfid_tim_emulate_start(FuriHalRfidEmulateCallback callback, void* context) { | ||||||
|  |     furi_assert(furi_hal_rfid); | ||||||
|  | 
 | ||||||
|  |     furi_hal_rfid->callback = callback; | ||||||
|  |     furi_hal_rfid->context = context; | ||||||
|  | 
 | ||||||
|     // TODO make api for interrupts priority
 |     // TODO make api for interrupts priority
 | ||||||
|     for(size_t i = WWDG_IRQn; i <= DMAMUX1_OVR_IRQn; i++) { |     for(size_t i = WWDG_IRQn; i <= DMAMUX1_OVR_IRQn; i++) { | ||||||
|         HAL_NVIC_SetPriority(i, 15, 0); |         HAL_NVIC_SetPriority(i, 15, 0); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     HAL_NVIC_SetPriority(TIM2_IRQn, 5, 0); |     furi_hal_interrupt_set_timer_isr(FURI_HAL_RFID_EMULATE_TIMER, furi_hal_rfid_emulate_isr); | ||||||
|     HAL_NVIC_EnableIRQ(TIM2_IRQn); |     NVIC_SetPriority( | ||||||
|  |         FURI_HAL_RFID_EMULATE_TIMER_IRQ, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0)); | ||||||
|  |     NVIC_EnableIRQ(FURI_HAL_RFID_EMULATE_TIMER_IRQ); | ||||||
| 
 | 
 | ||||||
|     HAL_TIM_PWM_Start_IT(&LFRFID_EMULATE_TIM, LFRFID_EMULATE_CHANNEL); |     LL_TIM_EnableIT_UPDATE(FURI_HAL_RFID_EMULATE_TIMER); | ||||||
|     HAL_TIM_Base_Start_IT(&LFRFID_EMULATE_TIM); |     LL_TIM_EnableAllOutputs(FURI_HAL_RFID_EMULATE_TIMER); | ||||||
|  |     LL_TIM_EnableCounter(FURI_HAL_RFID_EMULATE_TIMER); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_rfid_tim_emulate_stop() { | void furi_hal_rfid_tim_emulate_stop() { | ||||||
|     HAL_TIM_Base_Stop(&LFRFID_EMULATE_TIM); |     LL_TIM_DisableCounter(FURI_HAL_RFID_EMULATE_TIMER); | ||||||
|     HAL_TIM_PWM_Stop(&LFRFID_EMULATE_TIM, LFRFID_EMULATE_CHANNEL); |     LL_TIM_DisableAllOutputs(FURI_HAL_RFID_EMULATE_TIMER); | ||||||
|  |     furi_hal_interrupt_set_timer_isr(FURI_HAL_RFID_EMULATE_TIMER, NULL); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_rfid_tim_reset() { | void furi_hal_rfid_tim_reset() { | ||||||
|     FURI_CRITICAL_ENTER(); |     FURI_CRITICAL_ENTER(); | ||||||
| 
 | 
 | ||||||
|     HAL_TIM_Base_DeInit(&LFRFID_READ_TIM); |     LL_TIM_DeInit(FURI_HAL_RFID_READ_TIMER); | ||||||
|     LL_TIM_DeInit(TIM1); |     LL_TIM_DeInit(FURI_HAL_RFID_EMULATE_TIMER); | ||||||
|     HAL_TIM_Base_DeInit(&LFRFID_EMULATE_TIM); |  | ||||||
|     LL_TIM_DeInit(TIM2); |  | ||||||
| 
 | 
 | ||||||
|     FURI_CRITICAL_EXIT(); |     FURI_CRITICAL_EXIT(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool furi_hal_rfid_is_tim_emulate(TIM_HandleTypeDef* hw) { |  | ||||||
|     return (hw == &LFRFID_EMULATE_TIM); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void furi_hal_rfid_set_emulate_period(uint32_t period) { | void furi_hal_rfid_set_emulate_period(uint32_t period) { | ||||||
|     LFRFID_EMULATE_TIM.Instance->ARR = period; |     LL_TIM_SetAutoReload(FURI_HAL_RFID_EMULATE_TIMER, period); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_rfid_set_emulate_pulse(uint32_t pulse) { | void furi_hal_rfid_set_emulate_pulse(uint32_t pulse) { | ||||||
|     switch(LFRFID_EMULATE_CHANNEL) { | #if FURI_HAL_RFID_EMULATE_TIMER_CHANNEL == LL_TIM_CHANNEL_CH3 | ||||||
|     case TIM_CHANNEL_1: |     LL_TIM_OC_SetCompareCH3(FURI_HAL_RFID_EMULATE_TIMER, pulse); | ||||||
|         LFRFID_EMULATE_TIM.Instance->CCR1 = pulse; | #else | ||||||
|         break; | #error Update this code. Would you kindly? | ||||||
|     case TIM_CHANNEL_2: | #endif | ||||||
|         LFRFID_EMULATE_TIM.Instance->CCR2 = pulse; |  | ||||||
|         break; |  | ||||||
|     case TIM_CHANNEL_3: |  | ||||||
|         LFRFID_EMULATE_TIM.Instance->CCR3 = pulse; |  | ||||||
|         break; |  | ||||||
|     case TIM_CHANNEL_4: |  | ||||||
|         LFRFID_EMULATE_TIM.Instance->CCR4 = pulse; |  | ||||||
|         break; |  | ||||||
|     default: |  | ||||||
|         furi_crash(NULL); |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_rfid_set_read_period(uint32_t period) { | void furi_hal_rfid_set_read_period(uint32_t period) { | ||||||
|     LFRFID_TIM.Instance->ARR = period; |     LL_TIM_SetAutoReload(FURI_HAL_RFID_READ_TIMER, period); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_rfid_set_read_pulse(uint32_t pulse) { | void furi_hal_rfid_set_read_pulse(uint32_t pulse) { | ||||||
|     switch(LFRFID_READ_CHANNEL) { | #if FURI_HAL_RFID_READ_TIMER_CHANNEL == LL_TIM_CHANNEL_CH1N | ||||||
|     case TIM_CHANNEL_1: |     LL_TIM_OC_SetCompareCH1(FURI_HAL_RFID_READ_TIMER, pulse); | ||||||
|         LFRFID_TIM.Instance->CCR1 = pulse; | #else | ||||||
|         break; | #error Update this code. Would you kindly? | ||||||
|     case TIM_CHANNEL_2: | #endif | ||||||
|         LFRFID_TIM.Instance->CCR2 = pulse; |  | ||||||
|         break; |  | ||||||
|     case TIM_CHANNEL_3: |  | ||||||
|         LFRFID_TIM.Instance->CCR3 = pulse; |  | ||||||
|         break; |  | ||||||
|     case TIM_CHANNEL_4: |  | ||||||
|         LFRFID_TIM.Instance->CCR4 = pulse; |  | ||||||
|         break; |  | ||||||
|     default: |  | ||||||
|         furi_crash(NULL); |  | ||||||
|         break; |  | ||||||
|     } |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_rfid_change_read_config(float freq, float duty_cycle) { | void furi_hal_rfid_change_read_config(float freq, float duty_cycle) { | ||||||
|  | |||||||
| @ -732,10 +732,6 @@ void furi_hal_subghz_start_async_rx(FuriHalSubGhzCaptureCallback callback, void* | |||||||
|     LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH1); |     LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH1); | ||||||
|     LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH2); |     LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH2); | ||||||
| 
 | 
 | ||||||
|     // Enable NVIC
 |  | ||||||
|     NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0)); |  | ||||||
|     NVIC_EnableIRQ(TIM2_IRQn); |  | ||||||
| 
 |  | ||||||
|     // Start timer
 |     // Start timer
 | ||||||
|     LL_TIM_SetCounter(TIM2, 0); |     LL_TIM_SetCounter(TIM2, 0); | ||||||
|     LL_TIM_EnableCounter(TIM2); |     LL_TIM_EnableCounter(TIM2); | ||||||
| @ -919,6 +915,9 @@ bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void* | |||||||
|     LL_TIM_DisableMasterSlaveMode(TIM2); |     LL_TIM_DisableMasterSlaveMode(TIM2); | ||||||
| 
 | 
 | ||||||
|     furi_hal_interrupt_set_timer_isr(TIM2, furi_hal_subghz_async_tx_timer_isr); |     furi_hal_interrupt_set_timer_isr(TIM2, furi_hal_subghz_async_tx_timer_isr); | ||||||
|  |     NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0)); | ||||||
|  |     NVIC_EnableIRQ(TIM2_IRQn); | ||||||
|  | 
 | ||||||
|     LL_TIM_EnableIT_UPDATE(TIM2); |     LL_TIM_EnableIT_UPDATE(TIM2); | ||||||
|     LL_TIM_EnableDMAReq_UPDATE(TIM2); |     LL_TIM_EnableDMAReq_UPDATE(TIM2); | ||||||
|     LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH2); |     LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH2); | ||||||
| @ -930,10 +929,6 @@ bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void* | |||||||
| #endif | #endif | ||||||
|     furi_hal_subghz_tx(); |     furi_hal_subghz_tx(); | ||||||
| 
 | 
 | ||||||
|     // Enable NVIC
 |  | ||||||
|     NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0)); |  | ||||||
|     NVIC_EnableIRQ(TIM2_IRQn); |  | ||||||
| 
 |  | ||||||
|     LL_TIM_SetCounter(TIM2, 0); |     LL_TIM_SetCounter(TIM2, 0); | ||||||
|     LL_TIM_EnableCounter(TIM2); |     LL_TIM_EnableCounter(TIM2); | ||||||
|     return true; |     return true; | ||||||
|  | |||||||
| @ -62,8 +62,6 @@ C_SOURCES += \ | |||||||
| 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_pwr.c \
 | 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_pwr.c \
 | ||||||
| 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_pwr_ex.c \
 | 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_pwr_ex.c \
 | ||||||
| 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_rcc.c \
 | 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_rcc.c \
 | ||||||
| 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_tim.c \
 |  | ||||||
| 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_tim_ex.c \
 |  | ||||||
| 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_adc.c \
 | 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_adc.c \
 | ||||||
| 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_comp.c \
 | 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_comp.c \
 | ||||||
| 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_dma.c \
 | 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_dma.c \
 | ||||||
|  | |||||||
| @ -58,9 +58,11 @@ void furi_hal_rfid_tim_read_stop(); | |||||||
|  */ |  */ | ||||||
| void furi_hal_rfid_tim_emulate(float freq); | void furi_hal_rfid_tim_emulate(float freq); | ||||||
| 
 | 
 | ||||||
|  | typedef void (*FuriHalRfidEmulateCallback)(void* context); | ||||||
|  | 
 | ||||||
| /** Start emulation timer
 | /** Start emulation timer
 | ||||||
|  */ |  */ | ||||||
| void furi_hal_rfid_tim_emulate_start(); | void furi_hal_rfid_tim_emulate_start(FuriHalRfidEmulateCallback callback, void* context); | ||||||
| 
 | 
 | ||||||
| /** Stop emulation timer
 | /** Stop emulation timer
 | ||||||
|  */ |  */ | ||||||
| @ -70,14 +72,6 @@ void furi_hal_rfid_tim_emulate_stop(); | |||||||
|  */ |  */ | ||||||
| void furi_hal_rfid_tim_reset(); | void furi_hal_rfid_tim_reset(); | ||||||
| 
 | 
 | ||||||
| /** Check that timer instance is emulation timer
 |  | ||||||
|  * |  | ||||||
|  * @param      hw    timer instance |  | ||||||
|  * |  | ||||||
|  * @return     true if instance is emulation timer |  | ||||||
|  */ |  | ||||||
| bool furi_hal_rfid_is_tim_emulate(TIM_HandleTypeDef* hw); |  | ||||||
| 
 |  | ||||||
| /** Set emulation timer period
 | /** Set emulation timer period
 | ||||||
|  * |  * | ||||||
|  * @param      period  overall duration |  * @param      period  overall duration | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Aleksandr Kutuzov
						Aleksandr Kutuzov