Merge branch 'dev' into release-candidate
This commit is contained in:
		
						commit
						0d35596d96
					
				| @ -4,8 +4,6 @@ | ||||
| #include <furi.h> | ||||
| #include <furi_hal.h> | ||||
| 
 | ||||
| #include <loader/loader.h> | ||||
| 
 | ||||
| #include "animations/animation_manager.h" | ||||
| #include "desktop/scenes/desktop_scene.h" | ||||
| #include "desktop/scenes/desktop_scene_i.h" | ||||
| @ -15,6 +13,18 @@ | ||||
| #include "desktop_i.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) { | ||||
|     furi_assert(canvas); | ||||
|     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) { | ||||
|     furi_assert(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); | ||||
| } | ||||
| 
 | ||||
| @ -41,7 +61,6 @@ static void desktop_tick_event_callback(void* context) { | ||||
| Desktop* desktop_alloc() { | ||||
|     Desktop* desktop = malloc(sizeof(Desktop)); | ||||
| 
 | ||||
|     desktop->unload_animation_semaphore = osSemaphoreNew(1, 0, NULL); | ||||
|     desktop->animation_manager = animation_manager_alloc(); | ||||
|     desktop->gui = furi_record_open("gui"); | ||||
|     desktop->scene_thread = furi_thread_alloc(); | ||||
| @ -122,12 +141,13 @@ Desktop* desktop_alloc() { | ||||
|     gui_add_view_port(desktop->gui, desktop->lock_viewport, GuiLayerStatusBarLeft); | ||||
| 
 | ||||
|     // Special case: autostart application is already running
 | ||||
|     Loader* loader = furi_record_open("loader"); | ||||
|     if(loader_is_locked(loader) && | ||||
|     desktop->loader = furi_record_open("loader"); | ||||
|     if(loader_is_locked(desktop->loader) && | ||||
|        animation_manager_is_animation_loaded(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; | ||||
| } | ||||
| @ -135,6 +155,11 @@ Desktop* desktop_alloc() { | ||||
| void desktop_free(Desktop* 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, DesktopViewIdLockMenu); | ||||
|     view_dispatcher_remove_view(desktop->view_dispatcher, DesktopViewIdLocked); | ||||
| @ -159,8 +184,6 @@ void desktop_free(Desktop* desktop) { | ||||
|     popup_free(desktop->hw_mismatch_popup); | ||||
|     desktop_view_pin_timeout_free(desktop->pin_timeout_view); | ||||
| 
 | ||||
|     osSemaphoreDelete(desktop->unload_animation_semaphore); | ||||
| 
 | ||||
|     furi_record_close("gui"); | ||||
|     desktop->gui = NULL; | ||||
| 
 | ||||
|  | ||||
| @ -18,6 +18,8 @@ | ||||
| #include <gui/modules/popup.h> | ||||
| #include <gui/scene_manager.h> | ||||
| 
 | ||||
| #include <loader/loader.h> | ||||
| 
 | ||||
| #define STATUS_BAR_Y_SHIFT 13 | ||||
| 
 | ||||
| typedef enum { | ||||
| @ -57,7 +59,7 @@ struct Desktop { | ||||
|     ViewPort* lock_viewport; | ||||
| 
 | ||||
|     AnimationManager* animation_manager; | ||||
|     osSemaphoreId_t unload_animation_semaphore; | ||||
|     Loader* loader; | ||||
|     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); | ||||
|                 scene_manager_next_scene(desktop->scene_manager, DesktopSceneLocked); | ||||
|             } else { | ||||
|                 Loader* loader = furi_record_open("loader"); | ||||
|                 LoaderStatus status = | ||||
|                     loader_start(loader, "Desktop", DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG); | ||||
|                 furi_record_close("loader"); | ||||
|                     loader_start(desktop->loader, "Desktop", DESKTOP_SETTINGS_RUN_PIN_SETUP_ARG); | ||||
|                 if(status == LoaderStatusOk) { | ||||
|                     scene_manager_set_scene_state(desktop->scene_manager, DesktopSceneLockMenu, 1); | ||||
|                 } else { | ||||
|  | ||||
| @ -12,21 +12,6 @@ | ||||
| 
 | ||||
| #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) { | ||||
|     furi_assert(context); | ||||
|     Desktop* desktop = context; | ||||
| @ -85,12 +70,6 @@ void desktop_scene_main_on_enter(void* context) { | ||||
|     animation_manager_set_interact_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); | ||||
| 
 | ||||
|     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: | ||||
|             LOAD_DESKTOP_SETTINGS(&desktop->settings); | ||||
|             if(desktop->settings.favorite < FLIPPER_APPS_COUNT) { | ||||
|                 Loader* loader = furi_record_open("loader"); | ||||
|                 LoaderStatus status = | ||||
|                     loader_start(loader, FLIPPER_APPS[desktop->settings.favorite].name, NULL); | ||||
|                 LoaderStatus status = loader_start( | ||||
|                     desktop->loader, FLIPPER_APPS[desktop->settings.favorite].name, NULL); | ||||
|                 if(status != LoaderStatusOk) { | ||||
|                     FURI_LOG_E(TAG, "loader_start failed: %d", status); | ||||
|                 } | ||||
|                 furi_record_close("loader"); | ||||
|             } else { | ||||
|                 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); | ||||
|             consumed = true; | ||||
|             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: | ||||
|             desktop_view_locked_update(desktop->locked_view); | ||||
|             consumed = true; | ||||
| @ -177,16 +145,6 @@ bool desktop_scene_main_on_event(void* context, SceneManagerEvent event) { | ||||
| void desktop_scene_main_on_exit(void* 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_check_callback(desktop->animation_manager, NULL); | ||||
|     animation_manager_set_interact_callback(desktop->animation_manager, NULL); | ||||
|  | ||||
| @ -7,8 +7,6 @@ typedef enum { | ||||
|     DesktopMainEventOpenMenu, | ||||
|     DesktopMainEventOpenDebug, | ||||
|     DesktopMainEventRightShort, | ||||
|     DesktopMainEventBeforeAppStarted, | ||||
|     DesktopMainEventAfterAppFinished, | ||||
| 
 | ||||
|     DesktopLockedEventUnlocked, | ||||
|     DesktopLockedEventUpdate, | ||||
| @ -37,4 +35,7 @@ typedef enum { | ||||
|     DesktopAnimationEventNewIdleAnimation, | ||||
|     DesktopAnimationEventInteractAnimation, | ||||
| 
 | ||||
|     // Global events
 | ||||
|     DesktopGlobalBeforeAppStarted, | ||||
|     DesktopGlobalAfterAppFinished, | ||||
| } DesktopEvent; | ||||
|  | ||||
| @ -209,6 +209,7 @@ void ibutton_cli_emulate(Cli* cli, string_t args) { | ||||
| 
 | ||||
|     while(!exit) { | ||||
|         exit = cli_cmd_interrupt_received(cli); | ||||
|         delay(100); | ||||
|     }; | ||||
| 
 | ||||
|     worker->stop_emulate(); | ||||
|  | ||||
| @ -2,7 +2,6 @@ | ||||
| #include <furi.h> | ||||
| #include <furi_hal.h> | ||||
| #include <stm32wbxx_ll_cortex.h> | ||||
| #include <tim.h> | ||||
| 
 | ||||
| /**
 | ||||
|  * @brief private violation assistant for RfidReader | ||||
|  | ||||
| @ -1,7 +1,5 @@ | ||||
| #include "rfid_timer_emulator.h" | ||||
| 
 | ||||
| extern TIM_HandleTypeDef htim1; | ||||
| 
 | ||||
| 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_pins_emulate(); | ||||
| 
 | ||||
|             api_interrupt_add(timer_update_callback, InterruptTypeTimerUpdate, this); | ||||
| 
 | ||||
|             furi_hal_rfid_tim_emulate_start(); | ||||
|             furi_hal_rfid_tim_emulate_start(RfidTimerEmulator::timer_update_callback, this); | ||||
|         } | ||||
|     } else { | ||||
|         // not found
 | ||||
| @ -36,17 +32,13 @@ void RfidTimerEmulator::start(LfrfidKeyType type, const uint8_t* data, uint8_t d | ||||
| 
 | ||||
| void RfidTimerEmulator::stop() { | ||||
|     furi_hal_rfid_tim_emulate_stop(); | ||||
|     api_interrupt_remove(timer_update_callback, InterruptTypeTimerUpdate); | ||||
| 
 | ||||
|     furi_hal_rfid_tim_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); | ||||
|     TIM_HandleTypeDef* hw = static_cast<TIM_HandleTypeDef*>(_hw); | ||||
| 
 | ||||
|     if(furi_hal_rfid_is_tim_emulate(hw)) { | ||||
|     bool result; | ||||
|     bool polarity; | ||||
|     uint16_t period; | ||||
| @ -61,5 +53,4 @@ void RfidTimerEmulator::timer_update_callback(void* _hw, void* ctx) { | ||||
| 
 | ||||
|     furi_hal_rfid_set_emulate_period(period - 1); | ||||
|     furi_hal_rfid_set_emulate_pulse(pulse); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -25,5 +25,5 @@ private: | ||||
|     }; | ||||
| 
 | ||||
|     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; | ||||
| 
 | ||||
| typedef enum { | ||||
|     // Reserve first 50 events for application events
 | ||||
|     NfcWorkerEventReserved = 50, | ||||
| 
 | ||||
|     // Nfc worker common events
 | ||||
|     NfcWorkerEventSuccess, | ||||
|     NfcWorkerEventFail, | ||||
|     NfcWorkerEventNoCardDetected, | ||||
|  | ||||
| @ -1,7 +1,6 @@ | ||||
| #include "furi.h" | ||||
| 
 | ||||
| void furi_init() { | ||||
|     api_interrupt_init(); | ||||
|     furi_log_init(); | ||||
|     furi_record_init(); | ||||
|     furi_stdglue_init(); | ||||
|  | ||||
| @ -18,7 +18,6 @@ | ||||
| #include <furi/log.h> | ||||
| 
 | ||||
| #include <furi_hal_gpio.h> | ||||
| #include <furi_hal/api_interrupt_mgr.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_SMARTCARD_MODULE_ENABLED   */ | ||||
| /*#define HAL_SPI_MODULE_ENABLED    */ | ||||
| #define HAL_TIM_MODULE_ENABLED | ||||
| /*#define HAL_TIM_MODULE_ENABLED    */ | ||||
| /*#define HAL_TSC_MODULE_ENABLED    */ | ||||
| /*#define HAL_UART_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" | ||||
| 
 | ||||
| extern usbd_device udev; | ||||
| extern TIM_HandleTypeDef htim1; | ||||
| 
 | ||||
| extern void HW_TS_RTC_Wakeup_Handler(); | ||||
| extern void HW_IPCC_Tx_Handler(); | ||||
| @ -19,14 +18,6 @@ void USB_LP_IRQHandler(void) { | ||||
|     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) { | ||||
|     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 <tim.h> | ||||
| #include <gpio.h> | ||||
| 
 | ||||
| #include <stm32wbxx_ll_cortex.h> | ||||
| @ -22,11 +21,6 @@ void furi_hal_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_LOG_I(TAG, "iButton OK"); | ||||
|     furi_hal_speaker_init(); | ||||
|  | ||||
| @ -49,6 +49,11 @@ void furi_hal_ibutton_emulate_start( | ||||
|     LL_TIM_DeInit(FURI_HAL_IBUTTON_TIMER); | ||||
|     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_SetCounterMode(FURI_HAL_IBUTTON_TIMER, LL_TIM_COUNTERMODE_UP); | ||||
|     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); | ||||
| 
 | ||||
|     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); | ||||
| } | ||||
| 
 | ||||
| @ -80,6 +79,11 @@ void furi_hal_ibutton_emulate_stop() { | ||||
|     if(furi_hal_ibutton->state == FuriHalIbuttonStateRunning) { | ||||
|         furi_hal_ibutton->state = FuriHalIbuttonStateIdle; | ||||
|         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_ibutton->callback = NULL; | ||||
|  | ||||
| @ -3,7 +3,6 @@ | ||||
| #include <furi.h> | ||||
| #include <main.h> | ||||
| 
 | ||||
| #include <tim.h> | ||||
| #include <stm32wbxx_ll_tim.h> | ||||
| 
 | ||||
| #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 */ | ||||
| void TIM2_IRQHandler(void) { | ||||
|     if(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) { | ||||
|     if(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 */ | ||||
| void DMA1_Channel1_IRQHandler(void) { | ||||
|     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_ibutton.h> | ||||
| #include <furi_hal_interrupt.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_comp.h> | ||||
| 
 | ||||
| #define LFRFID_TIM htim1 | ||||
| #define LFRFID_CH TIM_CHANNEL_1 | ||||
| #define LFRFID_READ_TIM htim1 | ||||
| #define LFRFID_READ_CHANNEL TIM_CHANNEL_1 | ||||
| #define LFRFID_EMULATE_TIM htim2 | ||||
| #define LFRFID_EMULATE_CHANNEL TIM_CHANNEL_3 | ||||
| #define FURI_HAL_RFID_READ_TIMER TIM1 | ||||
| #define FURI_HAL_RFID_READ_TIMER_CHANNEL LL_TIM_CHANNEL_CH1N | ||||
| // We can't use N channel for LL_TIM_OC_Init, so...
 | ||||
| #define FURI_HAL_RFID_READ_TIMER_CHANNEL_CONFIG LL_TIM_CHANNEL_CH1 | ||||
| 
 | ||||
| #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() { | ||||
|     furi_assert(furi_hal_rfid == NULL); | ||||
|     furi_hal_rfid = malloc(sizeof(FuriHalRfid)); | ||||
| 
 | ||||
|     furi_hal_rfid_pins_reset(); | ||||
| 
 | ||||
|     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) { | ||||
|     // TODO LL init
 | ||||
|     uint32_t period = (uint32_t)((SystemCoreClock) / freq) - 1; | ||||
|     FURI_CRITICAL_ENTER(); | ||||
|     LL_TIM_DeInit(FURI_HAL_RFID_READ_TIMER); | ||||
|     FURI_CRITICAL_EXIT(); | ||||
| 
 | ||||
|     TIM_ClockConfigTypeDef sClockSourceConfig = {0}; | ||||
|     TIM_MasterConfigTypeDef sMasterConfig = {0}; | ||||
|     TIM_OC_InitTypeDef sConfigOC = {0}; | ||||
|     TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0}; | ||||
|     LL_TIM_InitTypeDef TIM_InitStruct = {0}; | ||||
|     TIM_InitStruct.Autoreload = (SystemCoreClock / freq) - 1; | ||||
|     LL_TIM_Init(FURI_HAL_RFID_READ_TIMER, &TIM_InitStruct); | ||||
|     LL_TIM_DisableARRPreload(FURI_HAL_RFID_READ_TIMER); | ||||
| 
 | ||||
|     // basic PWM setup with needed freq and internal clock
 | ||||
|     LFRFID_READ_TIM.Init.Prescaler = 0; | ||||
|     LFRFID_READ_TIM.Init.CounterMode = TIM_COUNTERMODE_UP; | ||||
|     LFRFID_READ_TIM.Init.Period = period; | ||||
|     LFRFID_READ_TIM.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; | ||||
|     LFRFID_READ_TIM.Init.RepetitionCounter = 0; | ||||
|     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(); | ||||
|     } | ||||
|     LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0}; | ||||
|     TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_PWM1; | ||||
|     TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_ENABLE; | ||||
|     TIM_OC_InitStruct.CompareValue = TIM_InitStruct.Autoreload * duty_cycle; | ||||
|     LL_TIM_OC_Init( | ||||
|         FURI_HAL_RFID_READ_TIMER, FURI_HAL_RFID_READ_TIMER_CHANNEL_CONFIG, &TIM_OC_InitStruct); | ||||
| 
 | ||||
|     // no master-slave mode
 | ||||
|     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(); | ||||
|     } | ||||
|     LL_TIM_EnableCounter(FURI_HAL_RFID_READ_TIMER); | ||||
| } | ||||
| 
 | ||||
| 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() { | ||||
|     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) { | ||||
|     // 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
 | ||||
|     LFRFID_EMULATE_TIM.Init.Prescaler = 0; | ||||
|     LFRFID_EMULATE_TIM.Init.CounterMode = TIM_COUNTERMODE_UP; | ||||
|     LFRFID_EMULATE_TIM.Init.Period = 1; | ||||
|     LFRFID_EMULATE_TIM.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; | ||||
|     LFRFID_EMULATE_TIM.Init.RepetitionCounter = 0; | ||||
|     LFRFID_EMULATE_TIM.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE; | ||||
|     if(HAL_TIM_Base_Init(&LFRFID_EMULATE_TIM) != HAL_OK) { | ||||
|         Error_Handler(); | ||||
|     } | ||||
|     FURI_CRITICAL_ENTER(); | ||||
|     LL_TIM_DeInit(FURI_HAL_RFID_EMULATE_TIMER); | ||||
|     FURI_CRITICAL_EXIT(); | ||||
| 
 | ||||
|     sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_ETRMODE2; | ||||
|     sClockSourceConfig.ClockPolarity = TIM_ETRPOLARITY_INVERTED; | ||||
|     sClockSourceConfig.ClockPrescaler = TIM_CLOCKPRESCALER_DIV1; | ||||
|     sClockSourceConfig.ClockFilter = 0; | ||||
|     if(HAL_TIM_ConfigClockSource(&LFRFID_EMULATE_TIM, &sClockSourceConfig) != HAL_OK) { | ||||
|         Error_Handler(); | ||||
|     } | ||||
|     if(HAL_TIM_PWM_Init(&LFRFID_EMULATE_TIM) != HAL_OK) { | ||||
|         Error_Handler(); | ||||
|     } | ||||
|     LL_TIM_SetPrescaler(FURI_HAL_RFID_EMULATE_TIMER, 0); | ||||
|     LL_TIM_SetCounterMode(FURI_HAL_RFID_EMULATE_TIMER, LL_TIM_COUNTERMODE_UP); | ||||
|     LL_TIM_SetAutoReload(FURI_HAL_RFID_EMULATE_TIMER, 1); | ||||
|     LL_TIM_DisableARRPreload(FURI_HAL_RFID_EMULATE_TIMER); | ||||
|     LL_TIM_SetRepetitionCounter(FURI_HAL_RFID_EMULATE_TIMER, 0); | ||||
| 
 | ||||
|     // 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(); | ||||
|     } | ||||
|     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); | ||||
| 
 | ||||
|     // 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(); | ||||
|     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); | ||||
| } | ||||
| 
 | ||||
| static void furi_hal_rfid_emulate_isr() { | ||||
|     if(LL_TIM_IsActiveFlag_UPDATE(FURI_HAL_RFID_EMULATE_TIMER)) { | ||||
|         LL_TIM_ClearFlag_UPDATE(FURI_HAL_RFID_EMULATE_TIMER); | ||||
|         furi_hal_rfid->callback(furi_hal_rfid->context); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 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
 | ||||
|     for(size_t i = WWDG_IRQn; i <= DMAMUX1_OVR_IRQn; i++) { | ||||
|         HAL_NVIC_SetPriority(i, 15, 0); | ||||
|     } | ||||
| 
 | ||||
|     HAL_NVIC_SetPriority(TIM2_IRQn, 5, 0); | ||||
|     HAL_NVIC_EnableIRQ(TIM2_IRQn); | ||||
|     furi_hal_interrupt_set_timer_isr(FURI_HAL_RFID_EMULATE_TIMER, furi_hal_rfid_emulate_isr); | ||||
|     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); | ||||
|     HAL_TIM_Base_Start_IT(&LFRFID_EMULATE_TIM); | ||||
|     LL_TIM_EnableIT_UPDATE(FURI_HAL_RFID_EMULATE_TIMER); | ||||
|     LL_TIM_EnableAllOutputs(FURI_HAL_RFID_EMULATE_TIMER); | ||||
|     LL_TIM_EnableCounter(FURI_HAL_RFID_EMULATE_TIMER); | ||||
| } | ||||
| 
 | ||||
| void furi_hal_rfid_tim_emulate_stop() { | ||||
|     HAL_TIM_Base_Stop(&LFRFID_EMULATE_TIM); | ||||
|     HAL_TIM_PWM_Stop(&LFRFID_EMULATE_TIM, LFRFID_EMULATE_CHANNEL); | ||||
|     LL_TIM_DisableCounter(FURI_HAL_RFID_EMULATE_TIMER); | ||||
|     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() { | ||||
|     FURI_CRITICAL_ENTER(); | ||||
| 
 | ||||
|     HAL_TIM_Base_DeInit(&LFRFID_READ_TIM); | ||||
|     LL_TIM_DeInit(TIM1); | ||||
|     HAL_TIM_Base_DeInit(&LFRFID_EMULATE_TIM); | ||||
|     LL_TIM_DeInit(TIM2); | ||||
|     LL_TIM_DeInit(FURI_HAL_RFID_READ_TIMER); | ||||
|     LL_TIM_DeInit(FURI_HAL_RFID_EMULATE_TIMER); | ||||
| 
 | ||||
|     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) { | ||||
|     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) { | ||||
|     switch(LFRFID_EMULATE_CHANNEL) { | ||||
|     case TIM_CHANNEL_1: | ||||
|         LFRFID_EMULATE_TIM.Instance->CCR1 = pulse; | ||||
|         break; | ||||
|     case TIM_CHANNEL_2: | ||||
|         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; | ||||
|     } | ||||
| #if FURI_HAL_RFID_EMULATE_TIMER_CHANNEL == LL_TIM_CHANNEL_CH3 | ||||
|     LL_TIM_OC_SetCompareCH3(FURI_HAL_RFID_EMULATE_TIMER, pulse); | ||||
| #else | ||||
| #error Update this code. Would you kindly? | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| 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) { | ||||
|     switch(LFRFID_READ_CHANNEL) { | ||||
|     case TIM_CHANNEL_1: | ||||
|         LFRFID_TIM.Instance->CCR1 = pulse; | ||||
|         break; | ||||
|     case TIM_CHANNEL_2: | ||||
|         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; | ||||
|     } | ||||
| #if FURI_HAL_RFID_READ_TIMER_CHANNEL == LL_TIM_CHANNEL_CH1N | ||||
|     LL_TIM_OC_SetCompareCH1(FURI_HAL_RFID_READ_TIMER, pulse); | ||||
| #else | ||||
| #error Update this code. Would you kindly? | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| 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_CH2); | ||||
| 
 | ||||
|     // Enable NVIC
 | ||||
|     NVIC_SetPriority(TIM2_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0)); | ||||
|     NVIC_EnableIRQ(TIM2_IRQn); | ||||
| 
 | ||||
|     // Start timer
 | ||||
|     LL_TIM_SetCounter(TIM2, 0); | ||||
|     LL_TIM_EnableCounter(TIM2); | ||||
| @ -919,6 +915,9 @@ bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void* | ||||
|     LL_TIM_DisableMasterSlaveMode(TIM2); | ||||
| 
 | ||||
|     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_EnableDMAReq_UPDATE(TIM2); | ||||
|     LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH2); | ||||
| @ -930,10 +929,6 @@ bool furi_hal_subghz_start_async_tx(FuriHalSubGhzAsyncTxCallback callback, void* | ||||
| #endif | ||||
|     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_EnableCounter(TIM2); | ||||
|     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_ex.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_comp.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); | ||||
| 
 | ||||
| typedef void (*FuriHalRfidEmulateCallback)(void* context); | ||||
| 
 | ||||
| /** Start emulation timer
 | ||||
|  */ | ||||
| void furi_hal_rfid_tim_emulate_start(); | ||||
| void furi_hal_rfid_tim_emulate_start(FuriHalRfidEmulateCallback callback, void* context); | ||||
| 
 | ||||
| /** Stop emulation timer
 | ||||
|  */ | ||||
| @ -70,14 +72,6 @@ void furi_hal_rfid_tim_emulate_stop(); | ||||
|  */ | ||||
| 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
 | ||||
|  * | ||||
|  * @param      period  overall duration | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Aleksandr Kutuzov
						Aleksandr Kutuzov