переношу проект пока не работает
This commit is contained in:
		
							parent
							
								
									5e93fc2099
								
							
						
					
					
						commit
						0f3ac734bf
					
				@ -30,7 +30,7 @@ extern "C" {
 | 
				
			|||||||
#include "stm32f1xx.h"
 | 
					#include "stm32f1xx.h"
 | 
				
			||||||
#include "Legacy/stm32_hal_legacy.h"
 | 
					#include "Legacy/stm32_hal_legacy.h"
 | 
				
			||||||
#include <stddef.h>
 | 
					#include <stddef.h>
 | 
				
			||||||
#include "mcu_wrapper_conf.h"
 | 
					//#include "mcu_wrapper_conf.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Exported types ------------------------------------------------------------*/
 | 
					/* Exported types ------------------------------------------------------------*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,7 @@
 | 
				
			|||||||
äĺôŕéíŕěč â stm32f4xx_matlab_conf.h.
 | 
					äĺôŕéíŕěč â stm32f4xx_matlab_conf.h.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**************************************************************************/
 | 
					**************************************************************************/
 | 
				
			||||||
 | 
					#include "stm32f1xx_matlab_conf.h"
 | 
				
			||||||
#include "mcu_wrapper_conf.h"
 | 
					#include "mcu_wrapper_conf.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
MCU_MemoryTypeDef MCU_MEM;
 | 
					MCU_MemoryTypeDef MCU_MEM;
 | 
				
			||||||
 | 
				
			|||||||
@ -7,7 +7,7 @@
 | 
				
			|||||||
#define _MATLAB_SETUP_H_
 | 
					#define _MATLAB_SETUP_H_
 | 
				
			||||||
#include "stm32_defs.h"
 | 
					#include "stm32_defs.h"
 | 
				
			||||||
#include "stm32f1xx_hal.h"
 | 
					#include "stm32f1xx_hal.h"
 | 
				
			||||||
//#include "mcu_wrapper_conf.h"
 | 
					#include "mcu_wrapper_conf.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DEFINES (UNCOMMENT WHAT YOU WILL SIMULATE)
 | 
					// DEFINES (UNCOMMENT WHAT YOU WILL SIMULATE)
 | 
				
			||||||
// TIMS
 | 
					// TIMS
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,57 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
 | 
					  "Code": {
 | 
				
			||||||
 | 
					    "Sources": {
 | 
				
			||||||
 | 
					      "Type": "files",
 | 
				
			||||||
 | 
					      "Options": [
 | 
				
			||||||
 | 
					        "Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c",
 | 
				
			||||||
 | 
					        "Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c",
 | 
				
			||||||
 | 
					        "Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.c",
 | 
				
			||||||
 | 
					        "Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.c",
 | 
				
			||||||
 | 
					        "Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c",
 | 
				
			||||||
 | 
					        "Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc.c",
 | 
				
			||||||
 | 
					        "Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_adc_ex.c",
 | 
				
			||||||
 | 
					        "Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c",
 | 
				
			||||||
 | 
					        "Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim_ex.c",
 | 
				
			||||||
 | 
					        "Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.c",
 | 
				
			||||||
 | 
					        "Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_exti.c",
 | 
				
			||||||
 | 
					        "stm32f1xx_matlab_conf.c",
 | 
				
			||||||
 | 
					        "Drivers/STM32F1xx_SIMULINK/stm32f1xx_matlab_gpio.c",
 | 
				
			||||||
 | 
					        "Drivers/STM32F1xx_SIMULINK/stm32f1xx_matlab_tim.c",
 | 
				
			||||||
 | 
					        "Drivers/STM32F1xx_SIMULINK/stm32f1xx_periph_registers.c"
 | 
				
			||||||
 | 
					      ]
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "Includes": {
 | 
				
			||||||
 | 
					      "Type": "paths",
 | 
				
			||||||
 | 
					      "Options": [
 | 
				
			||||||
 | 
					        "",
 | 
				
			||||||
 | 
					        "Drivers/STM32F1xx_SIMULINK",
 | 
				
			||||||
 | 
					        "Drivers/CMSIS",
 | 
				
			||||||
 | 
					        "Drivers/CMSIS/Device/STM32F1xx",
 | 
				
			||||||
 | 
					        "Drivers/STM32F1xx_HAL_Driver/Inc",
 | 
				
			||||||
 | 
					        "Drivers/STM32F1xx_HAL_Driver/Inc/Legacy"
 | 
				
			||||||
 | 
					      ]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "UserCode": {
 | 
				
			||||||
 | 
					    "Functions": {
 | 
				
			||||||
 | 
					      "PeriphInit": {
 | 
				
			||||||
 | 
					        "Options": [
 | 
				
			||||||
 | 
					          "Initialize_Periph_Sim()"
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "PeriphSimulation": {
 | 
				
			||||||
 | 
					        "Options": [
 | 
				
			||||||
 | 
					          "Simulate_TIMs()",
 | 
				
			||||||
 | 
					          "Simulate_GPIO_BSRR()"
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "PeriphDeinit": {
 | 
				
			||||||
 | 
					        "Options": [
 | 
				
			||||||
 | 
					          "deInitialize_Periph_Sim()"
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
  "RCC": {
 | 
					  "RCC": {
 | 
				
			||||||
    "Defines": {
 | 
					    "Defines": {
 | 
				
			||||||
      "HCLK_Clock": {
 | 
					      "HCLK_Clock": {
 | 
				
			||||||
@ -19,7 +19,7 @@
 | 
				
			|||||||
  * @{
 | 
					  * @{
 | 
				
			||||||
  */
 | 
					  */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define S_FUNCTION_NAME     MCU
 | 
					#define S_FUNCTION_NAME MCU
 | 
				
			||||||
#define S_FUNCTION_LEVEL    2
 | 
					#define S_FUNCTION_LEVEL    2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "mcu_wrapper_conf.h"
 | 
					#include "mcu_wrapper_conf.h"
 | 
				
			||||||
@ -111,16 +111,18 @@ static void mdlInitializeSizes(SimStruct* S)
 | 
				
			|||||||
	ssSetNumDiscStates(S, DISC_STATES_WIDTH);	// number of discrete states
 | 
						ssSetNumDiscStates(S, DISC_STATES_WIDTH);	// number of discrete states
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// set up input port
 | 
						// set up input port
 | 
				
			||||||
	if (!ssSetNumInputPorts(S, 1)) return;
 | 
						if (!ssSetNumInputPorts(S, IN_PORT_NUMB)) return;
 | 
				
			||||||
	for (int i = 0; i < IN_PORT_NUMB; i++)
 | 
						for (int i = 0; i < IN_PORT_NUMB; i++)
 | 
				
			||||||
		ssSetInputPortWidth(S, i, IN_PORT_WIDTH);
 | 
						{
 | 
				
			||||||
	ssSetInputPortDirectFeedThrough(S, 0, 0);
 | 
							ssSetInputPortWidth(S, i, inLengths[i]);
 | 
				
			||||||
	ssSetInputPortRequiredContiguous(S, 0, 1); // direct input signal access
 | 
							ssSetInputPortDirectFeedThrough(S, i, 0);
 | 
				
			||||||
 | 
							ssSetInputPortRequiredContiguous(S, i, 1);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// set up output port
 | 
						// set up output port
 | 
				
			||||||
	if (!ssSetNumOutputPorts(S, OUT_PORT_NUMB)) return;
 | 
						if (!ssSetNumOutputPorts(S, OUT_PORT_NUMB)) return;
 | 
				
			||||||
	for (int i = 0; i < OUT_PORT_NUMB; i++)
 | 
						for (int i = 0; i < OUT_PORT_NUMB; i++)
 | 
				
			||||||
		ssSetOutputPortWidth(S, i, OUT_PORT_WIDTH);
 | 
							ssSetOutputPortWidth(S, i, outLengths[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ssSetNumSampleTimes(S, 1);
 | 
						ssSetNumSampleTimes(S, 1);
 | 
				
			||||||
@ -152,7 +154,7 @@ static void mdlInitializeSizes(SimStruct* S)
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
static void mdlStart(SimStruct* S)
 | 
					static void mdlStart(SimStruct* S)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	SIM_Initialize_Simulation();
 | 
						SIM_Initialize_Simulation(S);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
#endif // MDL_START
 | 
					#endif // MDL_START
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -167,10 +169,10 @@ static void mdlStart(SimStruct* S)
 | 
				
			|||||||
static void mdlInitializeSampleTimes(SimStruct* S)
 | 
					static void mdlInitializeSampleTimes(SimStruct* S)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	// Шаг дискретизации
 | 
						// Шаг дискретизации
 | 
				
			||||||
	hmcu.SIM_Sample_Time = mxGetPr(ssGetSFcnParam(S, NPARAMS - 1))[0];
 | 
						hmcu.sSimSampleTime = mxGetPr(ssGetSFcnParam(S, NPARAMS - 1))[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Register one pair for each sample time
 | 
						// Register one pair for each sample time
 | 
				
			||||||
	ssSetSampleTime(S, 0, hmcu.SIM_Sample_Time);
 | 
						ssSetSampleTime(S, 0, hmcu.sSimSampleTime);
 | 
				
			||||||
	ssSetOffsetTime(S, 0, 0.0);
 | 
						ssSetOffsetTime(S, 0, 0.0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -189,7 +191,7 @@ static void mdlTerminate(SimStruct* S)
 | 
				
			|||||||
	ResumeThread(hmcu.hMCUThread);
 | 
						ResumeThread(hmcu.hMCUThread);
 | 
				
			||||||
	WaitForSingleObject(hmcu.hMCUThread, 10000);
 | 
						WaitForSingleObject(hmcu.hMCUThread, 10000);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	SIM_deInitialize_Simulation();
 | 
						SIM_deInitialize_Simulation(S);
 | 
				
			||||||
	mexUnlock();
 | 
						mexUnlock();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,138 +0,0 @@
 | 
				
			|||||||
/**
 | 
					 | 
				
			||||||
**************************************************************************
 | 
					 | 
				
			||||||
* @file app_wrapper.c
 | 
					 | 
				
			||||||
* @brief Код для из приложения МК для симуляции.
 | 
					 | 
				
			||||||
**************************************************************************
 | 
					 | 
				
			||||||
**************************************************************************/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#include "mcu_wrapper_conf.h"
 | 
					 | 
				
			||||||
// Includes START
 | 
					 | 
				
			||||||
#include "upp.h"
 | 
					 | 
				
			||||||
#include "main.h"
 | 
					 | 
				
			||||||
// Inlcudes END
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Dummy functions START
 | 
					 | 
				
			||||||
uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk) {}
 | 
					 | 
				
			||||||
void SystemClock_Config(void) {}
 | 
					 | 
				
			||||||
void Error_Handler(void) {}
 | 
					 | 
				
			||||||
// Dummy functions END
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void app_init(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
/* USER CODE BEGIN 1 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* USER CODE END 1 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* MCU Configuration--------------------------------------------------------*/
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
 | 
					 | 
				
			||||||
    HAL_Init();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* USER CODE BEGIN Init */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* USER CODE END Init */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* Configure the system clock */
 | 
					 | 
				
			||||||
    SystemClock_Config();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* USER CODE BEGIN SysInit */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* USER CODE END SysInit */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* Initialize all configured peripherals */
 | 
					 | 
				
			||||||
    MX_GPIO_Init();
 | 
					 | 
				
			||||||
    MX_TIM2_Init();
 | 
					 | 
				
			||||||
    /* USER CODE BEGIN 2 */
 | 
					 | 
				
			||||||
    upp_init();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* USER CODE END 2 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    /* Infinite loop */
 | 
					 | 
				
			||||||
    /* USER CODE BEGIN WHILE */
 | 
					 | 
				
			||||||
    //while (1)
 | 
					 | 
				
			||||||
    //{
 | 
					 | 
				
			||||||
    //    upp_main();
 | 
					 | 
				
			||||||
    //    /* USER CODE END WHILE */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    //    /* USER CODE BEGIN 3 */
 | 
					 | 
				
			||||||
    //}
 | 
					 | 
				
			||||||
    /* USER CODE END 3 */
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void app_step(void)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    upp_main();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void app_writeOutputBuffer(real_T* disc)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (int i = 0; i < PORT_WIDTH; i++)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        if (GPIOA->ODR & (1 << i))
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            disc[i] = 1;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (GPIOB->ODR & (1 << i))
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            disc[PORT_WIDTH + i] = 1;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    disc[2 * PORT_WIDTH + 0] = phase_A.ctrl.angle.delay_us;
 | 
					 | 
				
			||||||
    disc[2 * PORT_WIDTH + 1] = (uint16_t)((uint16_t)TIMER->CNT - phase_A.ctrl.angle.start_delay_tick);
 | 
					 | 
				
			||||||
    disc[2 * PORT_WIDTH + 2] = phase_A.ctrl.angle.start_delay_tick;
 | 
					 | 
				
			||||||
    disc[2 * PORT_WIDTH + 3] = TIMER->CNT;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void app_readInputs(real_T* in)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define detect_front(_in_numb_, _var_, _val_) {             \
 | 
					 | 
				
			||||||
if ((in[_in_numb_] > 0.5) && (prev_in[_in_numb_] <= 0.5))   \
 | 
					 | 
				
			||||||
{                                                           \
 | 
					 | 
				
			||||||
    _var_ = _val_;                                          \
 | 
					 | 
				
			||||||
} }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define detect_rise(_in_numb_, _var_, _val_) {              \
 | 
					 | 
				
			||||||
if ((in[_in_numb_] < 0.5) && (prev_in[_in_numb_] >= 0.5))   \
 | 
					 | 
				
			||||||
{                                                           \
 | 
					 | 
				
			||||||
    _var_ = _val_;                                          \
 | 
					 | 
				
			||||||
} }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    static real_T prev_in[IN_PORT_WIDTH];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    detect_front(0, phase_A.zc_detector.f.EXTIZeroCrossDetected, 1);
 | 
					 | 
				
			||||||
    detect_rise(0, phase_A.zc_detector.f.EXTIZeroCrossDetected, 1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    detect_front(1, phase_B.zc_detector.f.EXTIZeroCrossDetected, 1);
 | 
					 | 
				
			||||||
    detect_rise(1, phase_B.zc_detector.f.EXTIZeroCrossDetected, 1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    detect_front(2, phase_C.zc_detector.f.EXTIZeroCrossDetected, 1);
 | 
					 | 
				
			||||||
    detect_rise(2, phase_C.zc_detector.f.EXTIZeroCrossDetected, 1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    detect_front(3, Upp.GoSafe, 1);
 | 
					 | 
				
			||||||
    detect_rise(3, Upp.GoSafe, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    detect_front(4, Upp.Prepare, 1);
 | 
					 | 
				
			||||||
    detect_rise(4, Upp.Prepare, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    detect_front(5, Upp.ForceStop, 1);
 | 
					 | 
				
			||||||
    detect_rise(5, Upp.ForceStop, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    detect_front(6, Upp.ForceDisconnect, 1);
 | 
					 | 
				
			||||||
    detect_rise(6, Upp.ForceDisconnect, 0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    Upp.sine_freq = in[7];
 | 
					 | 
				
			||||||
    Upp.Duration = in[8];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for (int i = 0; i < IN_PORT_WIDTH; i++)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        prev_in[i] = in[i];
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							@ -7,6 +7,7 @@
 | 
				
			|||||||
Данный файл содержит функции для симуляции МК в Simulink (S-Function).
 | 
					Данный файл содержит функции для симуляции МК в Simulink (S-Function).
 | 
				
			||||||
**************************************************************************/
 | 
					**************************************************************************/
 | 
				
			||||||
#include "mcu_wrapper_conf.h"
 | 
					#include "mcu_wrapper_conf.h"
 | 
				
			||||||
 | 
					#include "app_wrapper.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
    * @addtogroup	WRAPPER_CONF
 | 
					    * @addtogroup	WRAPPER_CONF
 | 
				
			||||||
@ -15,6 +16,41 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
SIM__MCUHandleTypeDef hmcu;         ///< Хендл для управления потоком программы МК
 | 
					SIM__MCUHandleTypeDef hmcu;         ///< Хендл для управления потоком программы МК
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// INPUT/OUTPUTS AUTO-PARAMS START
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					  * @brief Таблица длин массивов IN
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					const int inLengths[IN_PORT_NUMB] = {
 | 
				
			||||||
 | 
					    IN_PORT_1_WIDTH,
 | 
				
			||||||
 | 
					    IN_PORT_2_WIDTH
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					  * @brief Таблица смещений в выходном массиве IN
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					const int inOffsets[IN_PORT_NUMB] = {
 | 
				
			||||||
 | 
					    OFFSET_IN_ARRAY_1,
 | 
				
			||||||
 | 
					    OFFSET_IN_ARRAY_2
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					  * @brief Таблица длин массивов OUT
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					const int outLengths[OUT_PORT_NUMB] = {
 | 
				
			||||||
 | 
					    OUT_PORT_1_WIDTH,
 | 
				
			||||||
 | 
					    OUT_PORT_2_WIDTH,
 | 
				
			||||||
 | 
					    OUT_PORT_3_WIDTH
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					  * @brief Таблица смещений в выходном массиве OUT
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					const int outOffsets[OUT_PORT_NUMB] = {
 | 
				
			||||||
 | 
					    OFFSET_OUT_ARRAY_1,
 | 
				
			||||||
 | 
					    OFFSET_OUT_ARRAY_2,
 | 
				
			||||||
 | 
					    OFFSET_OUT_ARRAY_3
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// INPUT/OUTPUTS AUTO-PARAMS END
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** MCU_WRAPPER
 | 
					/** MCU_WRAPPER
 | 
				
			||||||
    * @}
 | 
					    * @}
 | 
				
			||||||
    */
 | 
					    */
 | 
				
			||||||
@ -50,13 +86,13 @@ unsigned __stdcall MCU_App_Thread(void) {
 | 
				
			|||||||
  */
 | 
					  */
 | 
				
			||||||
void MCU_Step_Simulation(SimStruct* S, time_T time)
 | 
					void MCU_Step_Simulation(SimStruct* S, time_T time)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    hmcu.SystemClockDouble += hmcu.SystemClock_step; // emulate core clock 
 | 
					    hmcu.SystemClockDouble += hmcu.sSystemClock_step; // emulate core clock 
 | 
				
			||||||
    hmcu.SystemClock = hmcu.SystemClockDouble;
 | 
					    hmcu.SystemClock = hmcu.SystemClockDouble;
 | 
				
			||||||
    hmcu.SimTime = time;
 | 
					    hmcu.SimTime = time;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    MCU_readInputs(S); // считывание портов
 | 
					    MCU_readInputs(S); // считывание портов
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    MCU_Periph_Simulation(); // simulate peripheral
 | 
					    MCU_Periph_Simulation(S); // simulate peripheral
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef RUN_APP_MAIN_FUNC_THREAD
 | 
					#ifdef RUN_APP_MAIN_FUNC_THREAD
 | 
				
			||||||
    ResumeThread(hmcu.hMCUThread);
 | 
					    ResumeThread(hmcu.hMCUThread);
 | 
				
			||||||
@ -76,25 +112,26 @@ void MCU_Step_Simulation(SimStruct* S, time_T time)
 | 
				
			|||||||
  * @brief      Симуляция периферии МК
 | 
					  * @brief      Симуляция периферии МК
 | 
				
			||||||
  * @details    Пользовательский код, который симулирует работу периферии МК.
 | 
					  * @details    Пользовательский код, который симулирует работу периферии МК.
 | 
				
			||||||
  */
 | 
					  */
 | 
				
			||||||
void MCU_Periph_Simulation(void)
 | 
					void MCU_Periph_Simulation(SimStruct* S)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    uwTick = hmcu.SystemClock / (MCU_CORE_CLOCK / 1000);
 | 
					// PERIPH SIM START
 | 
				
			||||||
 | 
						Simulate_TIMs();
 | 
				
			||||||
    Simulate_TIMs();   
 | 
						Simulate_GPIO_BSRR();
 | 
				
			||||||
 | 
					// PERIPH SIM END
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* READ INPUTS S-FUNCTION TO MCU REGS */
 | 
					/* READ INPUTS S-FUNCTION TO MCU REGS */
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
  * @brief      Считывание входов S-Function в порты ввода-вывода.
 | 
					  * @brief      Считывание входов S-Function в порты ввода-вывода.
 | 
				
			||||||
 *	@param		S - указатель на структуру S-Function из "simstruc.h"
 | 
					 *	@param		S - указатель на структуру S-Function из "simstruc.h"
 | 
				
			||||||
  * @details    Пользовательский код, который записывает порты ввода-вывода из входов S-Function.
 | 
					  * @details    Пользовательский код, который записывает входы МК из входов S-Function.
 | 
				
			||||||
  */
 | 
					  */
 | 
				
			||||||
void MCU_readInputs(SimStruct* S)
 | 
					void MCU_readInputs(SimStruct* S)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /* Get S-Function inputs */
 | 
					    SIM_readInputs(S);
 | 
				
			||||||
    real_T* IN = ssGetInputPortRealSignal(S, 0);
 | 
					    /* Get S-Function descrete array (IO buffer) */
 | 
				
			||||||
 | 
					    real_T* In_Buff = ssGetDiscStates(S);
 | 
				
			||||||
    app_readInputs(IN);
 | 
					    app_readInputs(In_Buff);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* WRITE OUTPUTS BUFFER S-FUNCTION FROM MCU REGS*/
 | 
					/* WRITE OUTPUTS BUFFER S-FUNCTION FROM MCU REGS*/
 | 
				
			||||||
@ -105,10 +142,9 @@ void MCU_readInputs(SimStruct* S)
 | 
				
			|||||||
  */
 | 
					  */
 | 
				
			||||||
void MCU_writeOutputs(SimStruct* S)
 | 
					void MCU_writeOutputs(SimStruct* S)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    /* Get S-Function descrete array */
 | 
					    /* Get S-Function descrete array (IO buffer) */
 | 
				
			||||||
    real_T* Out_Buff = ssGetDiscStates(S);
 | 
					    real_T* Out_Buff = ssGetDiscStates(S);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Simulate_GPIO_BSRR();
 | 
					 | 
				
			||||||
    app_writeOutputBuffer(Out_Buff);
 | 
					    app_writeOutputBuffer(Out_Buff);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
//-----------------CONTROLLER SIMULATE FUNCTIONS---------------//
 | 
					//-----------------CONTROLLER SIMULATE FUNCTIONS---------------//
 | 
				
			||||||
@ -118,65 +154,129 @@ void MCU_writeOutputs(SimStruct* S)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
//-------------------------------------------------------------//
 | 
					//-------------------------------------------------------------//
 | 
				
			||||||
//----------------------SIMULINK FUNCTIONS---------------------//
 | 
					//----------------------SIMULINK FUNCTIONS---------------------//
 | 
				
			||||||
/* WRITE OUTPUTS OF S-BLOCK */
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
  * @brief      Формирование выходов S-Function.
 | 
					 | 
				
			||||||
 *	@param		S - указатель на структуру S-Function из "simstruc.h"
 | 
					 | 
				
			||||||
  * @details    Пользовательский код, который записывает выходы S-Function из буфера.
 | 
					 | 
				
			||||||
  */
 | 
					 | 
				
			||||||
void SIM_writeOutputs(SimStruct* S)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    real_T* GPIO;
 | 
					 | 
				
			||||||
    real_T* Out_Buff = ssGetDiscStates(S);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    //-------------WRITTING GPIOS---------------
 | 
					 | 
				
			||||||
    for (int j = 0; j < PORT_NUMB; j++)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        GPIO = ssGetOutputPortRealSignal(S, j);
 | 
					 | 
				
			||||||
        for (int i = 0; i < PORT_WIDTH; i++)
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            GPIO[i] = Out_Buff[j * PORT_WIDTH + i];
 | 
					 | 
				
			||||||
            Out_Buff[j * PORT_WIDTH + i] = 0;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    //------------------------------------------
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
/* MCU WRAPPER DEINITIALIZATION */
 | 
					/* MCU WRAPPER DEINITIALIZATION */
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
  * @brief      Инициализация симуляции МК.
 | 
					  * @brief      Инициализация симуляции МК.
 | 
				
			||||||
  * @details    Пользовательский код, который создает поток для приложения МК
 | 
					  * @details    Пользовательский код, который создает поток для приложения МК 
 | 
				
			||||||
                и настраивает симулятор МК для симуляции.
 | 
					                и настраивает симулятор МК для симуляции.
 | 
				
			||||||
  */
 | 
					  */
 | 
				
			||||||
void SIM_Initialize_Simulation(void)
 | 
					void SIM_Initialize_Simulation(SimStruct* S)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
#ifdef RUN_APP_MAIN_FUNC_THREAD
 | 
					#ifdef RUN_APP_MAIN_FUNC_THREAD
 | 
				
			||||||
    // инициализация потока, который будет выполнять код МК
 | 
					    // инициализация потока, который будет выполнять код МК
 | 
				
			||||||
    hmcu.hMCUThread = (HANDLE)CreateThread(NULL, 0, MCU_App_Thread, 0, CREATE_SUSPENDED, &hmcu.idMCUThread);
 | 
					    hmcu.hMCUThread = (HANDLE)CreateThread(NULL, 0, MCU_App_Thread, 0, CREATE_SUSPENDED, &hmcu.idMCUThread);
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
    extern int app_init(void);
 | 
					 | 
				
			||||||
    app_init();
 | 
					 | 
				
			||||||
#endif //RUN_APP_MAIN_FUNC_THREAD
 | 
					#endif //RUN_APP_MAIN_FUNC_THREAD
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* user initialization */
 | 
					    /* user initialization */
 | 
				
			||||||
    Initialize_Periph_Sim();
 | 
					    app_init();
 | 
				
			||||||
 | 
					// PERIPH INIT START
 | 
				
			||||||
    /* wrapper initialization */
 | 
						Initialize_Periph_Sim();
 | 
				
			||||||
    hmcu.SystemClock_step = MCU_CORE_CLOCK * hmcu.SIM_Sample_Time;   // set system clock step
 | 
					// PERIPH INIT END
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    /* clock step initialization */
 | 
				
			||||||
 | 
					    hmcu.sSystemClock_step = MCU_CORE_CLOCK * hmcu.sSimSampleTime;   // set system clock step
 | 
				
			||||||
 | 
					    hmcu.fInitDone = 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
/* MCU WRAPPER DEINITIALIZATION */
 | 
					/* MCU WRAPPER DEINITIALIZATION */
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
  * @brief      Деинициализация симуляции МК.
 | 
					  * @brief      Деинициализация симуляции МК.
 | 
				
			||||||
  * @details    Пользовательский код, который будет очищать все структуры после окончания симуляции.
 | 
					  * @details    Пользовательский код, который будет очищать все структуры после окончания симуляции.
 | 
				
			||||||
  */
 | 
					  */
 | 
				
			||||||
void SIM_deInitialize_Simulation(void)
 | 
					void SIM_deInitialize_Simulation(SimStruct* S)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
//#ifdef DEINITIALIZE_AFTER_SIM
 | 
					#ifdef DEINITIALIZE_AFTER_SIM
 | 
				
			||||||
#include "upp.h"
 | 
						// deinitialize app
 | 
				
			||||||
    memset(&Upp, 0, sizeof(Upp));
 | 
						app_deinit();
 | 
				
			||||||
    // simulate structures of peripheral deinitialization
 | 
					// PERIPH DEINIT START
 | 
				
			||||||
    deInitialize_Periph_Sim();
 | 
						deInitialize_Periph_Sim();
 | 
				
			||||||
    // mcu peripheral memory deinitialization
 | 
					// PERIPH DEINIT END
 | 
				
			||||||
    deInitialize_MCU();
 | 
					#endif// DEINITIALIZE_AFTER_SIM
 | 
				
			||||||
//#endif
 | 
					}
 | 
				
			||||||
 | 
					/* WORK WITH IN/OUT BUFFER OF S-BLOCK */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					  * @brief Функция для записи переменной в буфер выходов в определенный массив
 | 
				
			||||||
 | 
					  * @param xD           - указатель на буфер состояний
 | 
				
			||||||
 | 
					  * @param value        - значение для записи
 | 
				
			||||||
 | 
					  * @param array_index  - индекс выходного массива
 | 
				
			||||||
 | 
					  * @param value_index  - индекс внутри массива
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					void __WriteOutputArray(real_T* xD, float value, int array_index, int value_index)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (array_index >= OUT_PORT_NUMB)
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (value_index >= outLengths[array_index])
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int global_index = XD_OUTPUT_START + outOffsets[array_index] + value_index;
 | 
				
			||||||
 | 
					    xD[global_index] = value;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					  * @brief Функция для чтения значения из буфера входов из определенного массива
 | 
				
			||||||
 | 
					  * @param xD           - указатель на буфер состояний
 | 
				
			||||||
 | 
					  * @param array_index  - индекс входного массива
 | 
				
			||||||
 | 
					  * @param value_index  - индекс внутри массива
 | 
				
			||||||
 | 
					  * @return             - считанное значение или 0.0 при выходе за границы
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					float __ReadInputArray(const real_T* xD, int array_index, int value_index)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    if (array_index >= IN_PORT_NUMB)
 | 
				
			||||||
 | 
					        return 0.0f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (value_index >= inLengths[array_index])
 | 
				
			||||||
 | 
					        return 0.0f;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    int global_index = XD_INPUT_START + inOffsets[array_index] + value_index;
 | 
				
			||||||
 | 
					    return xD[global_index];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					  * @brief      Формирование выходов S-Function.
 | 
				
			||||||
 | 
					 *	@param		S - указатель на структуру S-Function из "simstruc.h"
 | 
				
			||||||
 | 
					  * @details    Пользовательский код, который записывает выходы S-Function из буфера дискретных состояний.
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					void SIM_writeOutputs(SimStruct* S)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    real_T* Output = ssGetOutputPortRealSignal(S,0);
 | 
				
			||||||
 | 
					    real_T* Out_Buff = ssGetDiscStates(S);
 | 
				
			||||||
 | 
					    int global_index;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //-------------WRITTING OUTPUT--------------
 | 
				
			||||||
 | 
					    for (int arr_ind = 0; arr_ind < OUT_PORT_NUMB; arr_ind++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Output = ssGetOutputPortRealSignal(S, arr_ind);
 | 
				
			||||||
 | 
					        for (int val_ind = 0; val_ind < outLengths[arr_ind]; val_ind++)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            global_index = XD_OUTPUT_START + outOffsets[arr_ind] + val_ind;
 | 
				
			||||||
 | 
					            Output[val_ind] = Out_Buff[global_index];
 | 
				
			||||||
 | 
					            Out_Buff[global_index] = 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    //------------------------------------------
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					  * @brief      Формирование входов S-Function.
 | 
				
			||||||
 | 
					 *	@param		S - указатель на структуру S-Function из "simstruc.h"
 | 
				
			||||||
 | 
					  * @details    Пользовательский код, который считывает входы S-Function в буфер дискретных состояний.
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					void SIM_readInputs(SimStruct* S)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    real_T* Input = ssGetInputPortRealSignal(S, 0);
 | 
				
			||||||
 | 
					    real_T* In_Buff = ssGetDiscStates(S);
 | 
				
			||||||
 | 
					    int global_index;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //-------------READING INPUTS---------------
 | 
				
			||||||
 | 
					    for (int arr_ind = 0; arr_ind < IN_PORT_NUMB; arr_ind++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        Input = ssGetInputPortRealSignal(S, arr_ind);
 | 
				
			||||||
 | 
					        for (int val_ind = 0; val_ind < inLengths[arr_ind]; val_ind++)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            global_index = XD_INPUT_START + inOffsets[arr_ind] + val_ind;
 | 
				
			||||||
 | 
					            In_Buff[global_index] = Input[val_ind];
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    //------------------------------------------
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
//-------------------------------------------------------------//
 | 
					//-------------------------------------------------------------//
 | 
				
			||||||
 | 
				
			|||||||
@ -2,11 +2,11 @@
 | 
				
			|||||||
**************************************************************************
 | 
					**************************************************************************
 | 
				
			||||||
* @dir ../MCU_Wrapper
 | 
					* @dir ../MCU_Wrapper
 | 
				
			||||||
* @brief <b> Папка с исходным кодом оболочки МК. </b>
 | 
					* @brief <b> Папка с исходным кодом оболочки МК. </b>
 | 
				
			||||||
* @details
 | 
					* @details 
 | 
				
			||||||
В этой папке содержаться оболочка(англ. wrapper) для запуска и контроля
 | 
					В этой папке содержаться оболочка(англ. wrapper) для запуска и контроля 
 | 
				
			||||||
эмуляции микроконтроллеров в MATLAB (любого МК, не только STM).
 | 
					эмуляции микроконтроллеров в MATLAB (любого МК, не только STM). 
 | 
				
			||||||
Оболочка представляет собой S-Function - блок в Simulink, который работает
 | 
					Оболочка представляет собой S-Function - блок в Simulink, который работает 
 | 
				
			||||||
по скомпилированому коду. Компиляция происходит с помощью MSVC-компилятора.
 | 
					по скомпилированому коду. Компиляция происходит с помощью MSVC-компилятора. 
 | 
				
			||||||
**************************************************************************/
 | 
					**************************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -25,56 +25,105 @@
 | 
				
			|||||||
#define _WRAPPER_CONF_H_
 | 
					#define _WRAPPER_CONF_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Includes
 | 
					// Includes
 | 
				
			||||||
#include "stm32f1xx_matlab_conf.h"  // For stm simulate functions
 | 
					 | 
				
			||||||
#include "simstruc.h"               // For S-Function variables
 | 
					#include "simstruc.h"               // For S-Function variables
 | 
				
			||||||
#include <process.h>                // For threads
 | 
					#include <process.h>                // For threads
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "app_includes.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
    * @defgroup	MCU_WRAPPER     MCU Wrapper
 | 
					    * @defgroup	MCU_WRAPPER     MCU Wrapper
 | 
				
			||||||
    * @brief 		Всякое для оболочки МК
 | 
					    * @brief 		Всякое для оболочки МК
 | 
				
			||||||
    */
 | 
					    */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					/**
 | 
				
			||||||
        * @addtogroup	WRAPPER_CONF    Wrapper Configuration
 | 
					    * @addtogroup	WRAPPER_CONF    Wrapper Configuration
 | 
				
			||||||
        * @ingroup		MCU_WRAPPER
 | 
					    * @ingroup		MCU_WRAPPER
 | 
				
			||||||
        * @brief 		Параметры конфигурации для оболочки МК
 | 
					    * @brief 		Параметры конфигурации для оболочки МК
 | 
				
			||||||
        * @details		Здесь дефайнами задается параметры оболочки, которые определяют как она будет работать
 | 
					    * @details		Здесь дефайнами задается параметры оболочки, которые определяют как она будет работать
 | 
				
			||||||
        * @{
 | 
					    * @{
 | 
				
			||||||
        */
 | 
					    */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // Parametrs of MCU simulator
 | 
					// Parametrs of MCU simulator
 | 
				
			||||||
//#define RUN_APP_MAIN_FUNC_THREAD                    ///< Enable using thread for MCU main() func
 | 
					//#define RUN_APP_MAIN_FUNC_THREAD                    ///< Enable using thread for MCU main() func
 | 
				
			||||||
//#define DEKSTOP_CYCLES_FOR_MCU_APP      0xFF      ///< number of for() cycles after which MCU thread would be suspended 
 | 
					//#define DEKSTOP_CYCLES_FOR_MCU_APP      0xFFFF      ///< number of for() cycles after which MCU thread would be suspended 
 | 
				
			||||||
//#define MCU_CORE_CLOCK                  72000000
 | 
					//#define MCU_CORE_CLOCK                  150000000   ///< MCU clock rate for simulation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
//#define DEINITIALIZE_AFTER_SIM                    ///< Enable deinitializing structures at simulation ends
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define PORT_WIDTH                      16          ///< width of one port
 | 
					 | 
				
			||||||
#define PORT_NUMB                       3           ///< amount of ports
 | 
					 | 
				
			||||||
// Parameters of S_Function
 | 
					// Parameters of S_Function
 | 
				
			||||||
#define NPARAMS                 1                           ///< number of input parametrs (only Ts)
 | 
					// INPUT/OUTPUTS PARAMS START
 | 
				
			||||||
#define IN_PORT_WIDTH           (9)                         ///< width of input ports
 | 
					#define IN_PORT_NUMB           2
 | 
				
			||||||
#define IN_PORT_NUMB            1                           ///< number of input ports
 | 
					#define IN_PORT_1_WIDTH        3
 | 
				
			||||||
#define OUT_PORT_WIDTH          PORT_WIDTH                  ///< width of output ports
 | 
					#define IN_PORT_2_WIDTH        6
 | 
				
			||||||
#define OUT_PORT_NUMB           PORT_NUMB                   ///< number of output ports
 | 
					 | 
				
			||||||
#define DISC_STATES_WIDTH       PORT_WIDTH*PORT_NUMB        ///< width of discrete states array
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define OUT_PORT_NUMB           3
 | 
				
			||||||
 | 
					#define OUT_PORT_1_WIDTH        16
 | 
				
			||||||
 | 
					#define OUT_PORT_2_WIDTH        16
 | 
				
			||||||
 | 
					#define OUT_PORT_3_WIDTH        16
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// INPUT/OUTPUTS PARAMS END
 | 
				
			||||||
/** WRAPPER_CONF
 | 
					/** WRAPPER_CONF
 | 
				
			||||||
  * @}
 | 
					  * @}
 | 
				
			||||||
  */
 | 
					  */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  /**
 | 
					 | 
				
			||||||
    * @addtogroup	MCU_WRAPPER
 | 
					 | 
				
			||||||
    * @{
 | 
					 | 
				
			||||||
    */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Fixed parameters(?) of S_Function
 | 
					/**
 | 
				
			||||||
 | 
					  * @addtogroup	MCU_WRAPPER
 | 
				
			||||||
 | 
					  * @{
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @brief Записывает значение в выходной массив блока S-Function
 | 
				
			||||||
 | 
					  * @param _var_ Значение, которое необходимо записать (будет преобразовано в float)
 | 
				
			||||||
 | 
					  * @param _arr_ind_ Индекс выходного порта
 | 
				
			||||||
 | 
					  * @param _val_ind_ Индекс элемента в выходном массиве
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					#define	WriteOutputArray(_var_, _arr_ind_, _val_ind_)	__WriteOutputArray(Buffer, (float)_var_, _arr_ind_, _val_ind_)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** @brief Считывает значение из входного массива блока S-Function
 | 
				
			||||||
 | 
					  * @param _var_ Значение, которое необходимо записать (будет преобразовано в float)
 | 
				
			||||||
 | 
					  * @param _arr_ind_ Индекс входного порта
 | 
				
			||||||
 | 
					  * @param _val_ind_ Индекс элемента во входном массиве
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					#define	ReadInputArray(_arr_ind_, _val_ind_)		__ReadInputArray(Buffer, _arr_ind_, _val_ind_)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// INPUT/OUTPUTS AUTO-PARAMS START
 | 
				
			||||||
 | 
					/// === Полный размер буфера ===
 | 
				
			||||||
 | 
					#define TOTAL_IN_SIZE (IN_PORT_1_WIDTH + IN_PORT_2_WIDTH)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// === Смещения массивов (внутри общего буфера) ===
 | 
				
			||||||
 | 
					#define OFFSET_IN_ARRAY_1 0
 | 
				
			||||||
 | 
					#define OFFSET_IN_ARRAY_2 (OFFSET_IN_ARRAY_1 + IN_PORT_1_WIDTH)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// === Полный размер буфера ===
 | 
				
			||||||
 | 
					#define TOTAL_OUT_SIZE (OUT_PORT_1_WIDTH + OUT_PORT_2_WIDTH + OUT_PORT_3_WIDTH)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// === Смещения массивов (внутри общего буфера) ===
 | 
				
			||||||
 | 
					#define OFFSET_OUT_ARRAY_1 0
 | 
				
			||||||
 | 
					#define OFFSET_OUT_ARRAY_2 (OFFSET_OUT_ARRAY_1 + OUT_PORT_1_WIDTH)
 | 
				
			||||||
 | 
					#define OFFSET_OUT_ARRAY_3 (OFFSET_OUT_ARRAY_2 + OUT_PORT_2_WIDTH)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// INPUT/OUTPUTS AUTO-PARAMS END
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					extern const int outLengths[OUT_PORT_NUMB];
 | 
				
			||||||
 | 
					extern const int outOffsets[OUT_PORT_NUMB];
 | 
				
			||||||
 | 
					extern const int inLengths[IN_PORT_NUMB];
 | 
				
			||||||
 | 
					extern const int inOffsets[IN_PORT_NUMB];
 | 
				
			||||||
 | 
					#define TOTAL_XD_SIZE (TOTAL_IN_SIZE + TOTAL_OUT_SIZE)
 | 
				
			||||||
 | 
					#define XD_INPUT_START      0
 | 
				
			||||||
 | 
					#define XD_OUTPUT_START     (XD_INPUT_START + TOTAL_IN_SIZE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Fixed parameters(?) of S_Function
 | 
				
			||||||
#define NPARAMS                 1                               ///< number of input parametrs (only Ts)
 | 
					#define NPARAMS                 1                               ///< number of input parametrs (only Ts)
 | 
				
			||||||
#define DISC_STATES_WIDTH       OUT_PORT_WIDTH*OUT_PORT_NUMB    ///< width of discrete states array (outbup buffer)
 | 
					#define DISC_STATES_WIDTH       TOTAL_XD_SIZE    ///< width of discrete states array (outbup buffer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
  * @brief      Define for creating thread in suspended state.
 | 
					  * @brief      Define for creating thread in suspended state.
 | 
				
			||||||
  * @details    Define from WinBase.h. We dont wanna include "Windows.h" or smth like this, because of HAL there are a lot of redefine errors.
 | 
					  * @details    Define from WinBase.h. We dont wanna include "Windows.h" or smth like this, because of HAL there are a lot of redefine errors.
 | 
				
			||||||
@ -83,21 +132,23 @@
 | 
				
			|||||||
typedef void* HANDLE; ///< MCU handle typedef
 | 
					typedef void* HANDLE; ///< MCU handle typedef
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
  * @brief  MCU handle Structure definition.
 | 
					  * @brief  MCU handle Structure definition. 
 | 
				
			||||||
  * @note 	Prefixes: h - handle, s - settings, f - flag
 | 
					  * @note 	Prefixes: h - handle, s - settings, f - flag
 | 
				
			||||||
  */
 | 
					  */
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    // MCU Thread
 | 
					    // MCU Thread
 | 
				
			||||||
    HANDLE          hMCUThread;                 ///< Хендл для потока МК
 | 
					    HANDLE          hMCUThread;                 ///< Хендл для потока МК
 | 
				
			||||||
    uint32_t        idMCUThread;                ///< id потока МК (unused)
 | 
					    int             idMCUThread;                ///< id потока МК (unused)
 | 
				
			||||||
    // Flags
 | 
					    // Flags
 | 
				
			||||||
    unsigned        fMCU_Stop : 1;              ///< флаг для выхода из потока программы МК
 | 
					    unsigned        fMCU_Stop : 1;              ///< флаг для выхода из потока программы МК
 | 
				
			||||||
    double          SIM_Sample_Time;            ///< sample time of simulation
 | 
					    unsigned        fInitDone : 1;              ///< флаг для выхода из потока программы МК
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    double          SimTime;                    ///< Текущее время симуляции
 | 
				
			||||||
 | 
					    long            SystemClock;                ///< Счетчик тактов для симуляции системных тиков (в целочисленном формате)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    double          SystemClockDouble;          ///< Счетчик в формате double для точной симуляции системных тиков С промежуточными значений
 | 
					    double          SystemClockDouble;          ///< Счетчик в формате double для точной симуляции системных тиков С промежуточными значений
 | 
				
			||||||
    uint64_t        SystemClock;                ///< Счетчик тактов для симуляции системных тиков (в целочисленном формате)
 | 
					    double          sSystemClock_step;          ///< Шаг тиков для их симуляции, в формате double
 | 
				
			||||||
    double          SystemClock_step;           ///< Шаг тиков для их симуляции, в формате double
 | 
					    double          sSimSampleTime;             ///< Период дискретизации симуляции
 | 
				
			||||||
    double          SimTime;
 | 
					 | 
				
			||||||
}SIM__MCUHandleTypeDef;
 | 
					}SIM__MCUHandleTypeDef;
 | 
				
			||||||
extern SIM__MCUHandleTypeDef hmcu;              // extern для видимости переменной во всех файлах
 | 
					extern SIM__MCUHandleTypeDef hmcu;              // extern для видимости переменной во всех файлах
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -112,54 +163,62 @@ extern SIM__MCUHandleTypeDef hmcu;              // extern для видимос
 | 
				
			|||||||
  */
 | 
					  */
 | 
				
			||||||
#define while(_expression_)                          sim_while(_expression_) 
 | 
					#define while(_expression_)                          sim_while(_expression_) 
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
  /* SIMULINK WHILE */
 | 
					
 | 
				
			||||||
  /**
 | 
					/* SIMULINK WHILE */
 | 
				
			||||||
    * @brief      While statement for emulate MCU code in Simulink.
 | 
					/**
 | 
				
			||||||
    * @param      _expression_ - expression for while.
 | 
					  * @brief      While statement for emulate MCU code in Simulink.
 | 
				
			||||||
    * @details    Данный while необходим, чтобы в конце симуляции, завершить поток МК:
 | 
					  * @param      _expression_ - expression for while.
 | 
				
			||||||
    *             При выставлении флага окончания симуляции, все while будут пропускаться
 | 
					  * @details    Данный while необходим, чтобы в конце симуляции, завершить поток МК:
 | 
				
			||||||
    *             и поток сможет дойти до конца функции main и завершить себя.
 | 
					  *             При выставлении флага окончания симуляции, все while будут пропускаться 
 | 
				
			||||||
    */
 | 
					  *             и поток сможет дойти до конца функции main и завершить себя. 
 | 
				
			||||||
 | 
					  */    
 | 
				
			||||||
#define sim_while(_expression_)                     while((_expression_)&&(hmcu.fMCU_Stop == 0))
 | 
					#define sim_while(_expression_)                     while((_expression_)&&(hmcu.fMCU_Stop == 0))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* DEFAULT WHILE */
 | 
					/* DEFAULT WHILE */
 | 
				
			||||||
    /**
 | 
					/**
 | 
				
			||||||
      * @brief      Default/Native C while statement.
 | 
					  * @brief      Default/Native C while statement.
 | 
				
			||||||
      * @param      _expression_ - expression for while.
 | 
					  * @param      _expression_ - expression for while.
 | 
				
			||||||
      * @details    Данный while - аналог обычного while, без дополнительного функционала.
 | 
					  * @details    Данный while - аналог обычного while, без дополнительного функционала.
 | 
				
			||||||
      */
 | 
					  */
 | 
				
			||||||
#define native_while(_expression_)                   for(; (_expression_); )
 | 
					#define native_while(_expression_)                   for(; (_expression_); )
 | 
				
			||||||
      /***************************************************************/
 | 
					  /***************************************************************/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //------------------  SIMULINK WHILE DEFINES  -----------------//
 | 
					//------------------  SIMULINK WHILE DEFINES  -----------------//
 | 
				
			||||||
    //-------------------------------------------------------------//
 | 
					//-------------------------------------------------------------//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //-------------------------------------------------------------//
 | 
					//-------------------------------------------------------------//
 | 
				
			||||||
    //---------------- SIMULATE FUNCTIONS PROTOTYPES  -------------//
 | 
					//---------------- SIMULATE FUNCTIONS PROTOTYPES  -------------//
 | 
				
			||||||
    /* Step simulation */
 | 
					/* Step simulation */
 | 
				
			||||||
void MCU_Step_Simulation(SimStruct* S, time_T time);
 | 
					void MCU_Step_Simulation(SimStruct *S, time_T time);     
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* MCU peripheral simulation */
 | 
					/* MCU peripheral simulation */
 | 
				
			||||||
void MCU_Periph_Simulation(void);
 | 
					void MCU_Periph_Simulation(SimStruct* S);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Initialize MCU simulation */
 | 
					/* Initialize MCU simulation */
 | 
				
			||||||
void SIM_Initialize_Simulation(void);
 | 
					void SIM_Initialize_Simulation(SimStruct* S);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Deinitialize MCU simulation */
 | 
					/* Deinitialize MCU simulation */
 | 
				
			||||||
void SIM_deInitialize_Simulation(void);
 | 
					void SIM_deInitialize_Simulation(SimStruct* S);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Read inputs S-function  */
 | 
					/* Read inputs S-function  */
 | 
				
			||||||
void MCU_readInputs(SimStruct* S);
 | 
					void MCU_readInputs(SimStruct* S);
 | 
				
			||||||
void app_readInputs(real_T* in);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Write pre-outputs S-function (out_buff states) */
 | 
					/* Write pre-outputs S-function (out_buff states) */
 | 
				
			||||||
void MCU_writeOutputs(SimStruct* S);
 | 
					void MCU_writeOutputs(SimStruct* S);
 | 
				
			||||||
void app_writeOutputBuffer(real_T* disc);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Write outputs of block of S-Function*/
 | 
					/* Write outputs of block of S-Function*/
 | 
				
			||||||
void SIM_writeOutput(SimStruct* S);
 | 
					void SIM_writeOutputs(SimStruct* S);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Write inputs of block of S-Function*/
 | 
				
			||||||
 | 
					void SIM_readInputs(SimStruct* S);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Set output of block of S-Function*/
 | 
				
			||||||
 | 
					void __WriteOutputArray(real_T* xD, float value, int array_index, int value_index);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Get input of block of S-Function*/
 | 
				
			||||||
 | 
					float __ReadInputArray(const real_T* xD, int array_index, int value_index);
 | 
				
			||||||
//---------------- SIMULATE FUNCTIONS PROTOTYPES  -------------//
 | 
					//---------------- SIMULATE FUNCTIONS PROTOTYPES  -------------//
 | 
				
			||||||
//-------------------------------------------------------------//
 | 
					//-------------------------------------------------------------//
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -169,14 +228,14 @@ void SIM_writeOutput(SimStruct* S);
 | 
				
			|||||||
#endif // _WRAPPER_CONF_H_
 | 
					#endif // _WRAPPER_CONF_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    //-------------------------------------------------------------//
 | 
					//-------------------------------------------------------------//
 | 
				
			||||||
    //---------------------BAT FILE DESCRIBTION--------------------//
 | 
					//---------------------BAT FILE DESCRIBTION--------------------//
 | 
				
			||||||
    /**
 | 
					/**
 | 
				
			||||||
      * @file run_mex.bat
 | 
					  * @file run_mex.bat
 | 
				
			||||||
      * @brief Батник для компиляции оболочки МК.
 | 
					  * @brief Батник для компиляции оболочки МК.
 | 
				
			||||||
      * @details
 | 
					  * @details
 | 
				
			||||||
      * Вызывается в матлабе из mexing.m.
 | 
					  * Вызывается в матлабе из allmex.m.
 | 
				
			||||||
      *
 | 
					  * 
 | 
				
			||||||
      * Исходный код батника:
 | 
					  * Исходный код батника:
 | 
				
			||||||
      * @include F:\Work\Projects\MATLAB\matlab_stm_emulate\MCU_Wrapper\run_mex.bat
 | 
					  * @include run_mex.bat
 | 
				
			||||||
      */
 | 
					  */
 | 
				
			||||||
@ -1,718 +0,0 @@
 | 
				
			|||||||
% Компилирует S-function
 | 
					 | 
				
			||||||
function mexing(compile_mode)
 | 
					 | 
				
			||||||
    global Ts
 | 
					 | 
				
			||||||
    Ts = 0.00001;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    if compile_mode == 1
 | 
					 | 
				
			||||||
        delete("*.mexw64")
 | 
					 | 
				
			||||||
        delete("*.mexw64.pdb")
 | 
					 | 
				
			||||||
        delete(".\MCU_Wrapper\Outputs\*.*");
 | 
					 | 
				
			||||||
        set_param(gcb, 'consoleOutput', '');    
 | 
					 | 
				
			||||||
        % Дефайны
 | 
					 | 
				
			||||||
        definesWrapperArg = buildWrapperDefinesString();
 | 
					 | 
				
			||||||
        definesUserArg = parseDefinesMaskText();
 | 
					 | 
				
			||||||
        definesConfigArg = buildConfigDefinesString();
 | 
					 | 
				
			||||||
        definesAllArg = [definesUserArg + " " + definesWrapperArg  + " " + definesConfigArg];    
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
        %режимы компиляции
 | 
					 | 
				
			||||||
        if read_checkbox('enableDebug')
 | 
					 | 
				
			||||||
            modeArg = "debug";
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            modeArg = "release";
 | 
					 | 
				
			||||||
        end    
 | 
					 | 
				
			||||||
        if read_checkbox('fullOutput') || read_checkbox('extConsol') 
 | 
					 | 
				
			||||||
            echoArg = 'echo_enable';
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            echoArg = 'echo_disable';    
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        [includesArg, codeArg] = make_mex_arguments('incTable', 'srcTable');
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        % Вызов батника с двумя параметрами: includes и code
 | 
					 | 
				
			||||||
        cmd = sprintf('.\\MCU_Wrapper\\run_mex.bat "%s" "%s" "%s" %s %s', includesArg, codeArg, definesAllArg, modeArg, echoArg);
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
        if read_checkbox('extConsol')
 | 
					 | 
				
			||||||
            cmdout = runBatAndShowOutput(cmd);
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            [status, cmdout]= system(cmd);
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        % Сохраним вывод в параметр маски с именем 'consoleOutput'
 | 
					 | 
				
			||||||
        set_param(gcb, 'consoleOutput', cmdout);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        beep
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
        blockPath = bdroot;
 | 
					 | 
				
			||||||
        config = read_periph_config();
 | 
					 | 
				
			||||||
        config = update_config_from_mask(blockPath, config);
 | 
					 | 
				
			||||||
        write_periph_config(config);
 | 
					 | 
				
			||||||
        update_mask_from_config(blockPath, config);
 | 
					 | 
				
			||||||
        % set_param(gcb, 'consoleOutput', 'Peripheral configuration file loaded. Re-open Block Parameters');
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
%% COMPILE PARAMS
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function [includesArg, codeArg] = make_mex_arguments(incTableName, srcTableame)
 | 
					 | 
				
			||||||
%MAKE_MEX_ARGUMENTS Формирует строки аргументов для вызова mex-компиляции через батник
 | 
					 | 
				
			||||||
%
 | 
					 | 
				
			||||||
% [includesArg, codeArg] = make_mex_arguments(includesCell, codeCell)
 | 
					 | 
				
			||||||
%
 | 
					 | 
				
			||||||
% Вход:
 | 
					 | 
				
			||||||
%   includesCell — ячейковый массив путей к директориям include
 | 
					 | 
				
			||||||
%   codeCell     — ячейковый массив исходных файлов
 | 
					 | 
				
			||||||
%
 | 
					 | 
				
			||||||
% Выход:
 | 
					 | 
				
			||||||
%   includesArg  — строка для передачи в батник, например: "-I"inc1" -I"inc2""
 | 
					 | 
				
			||||||
%   codeArg      — строка с исходниками, например: ""src1.c" "src2.cpp""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Здесь пример получения из маски текущего блока (замени по своему)
 | 
					 | 
				
			||||||
    blockHandle = gcbh;  % или замени на нужный блок
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    includesCell = parseCellString(get_param(blockHandle, incTableName));
 | 
					 | 
				
			||||||
    codeCell = parseCellString(get_param(blockHandle, srcTableame));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Оборачиваем пути в кавычки и добавляем -I
 | 
					 | 
				
			||||||
    includesStr = strjoin(cellfun(@(f) ['-I"' f '"'], includesCell, 'UniformOutput', false), ' ');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Оборачиваем имена файлов в кавычки
 | 
					 | 
				
			||||||
    codeStr = strjoin(cellfun(@(f) ['"' f '"'], codeCell, 'UniformOutput', false), ' ');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Удаляем символ переноса строки и пробел в конце, если вдруг попал
 | 
					 | 
				
			||||||
    codeStr = strtrim(codeStr);
 | 
					 | 
				
			||||||
    includesStr = strtrim(includesStr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Оборачиваем всю строку в кавычки, чтобы батник корректно понял
 | 
					 | 
				
			||||||
    % includesArg = ['"' includesStr '"'];
 | 
					 | 
				
			||||||
    % codeArg = ['"' codeStr '"'];
 | 
					 | 
				
			||||||
    includesArg = includesStr;
 | 
					 | 
				
			||||||
    codeArg = codeStr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function definesWrapperArg = buildWrapperDefinesString()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    definesWrapperArg = '';
 | 
					 | 
				
			||||||
    definesWrapperArg = addDefineByParam(definesWrapperArg, 'enableThreading', 0);
 | 
					 | 
				
			||||||
    definesWrapperArg = addDefineByParam(definesWrapperArg, 'enableDeinit', 0);
 | 
					 | 
				
			||||||
    definesWrapperArg = addDefineByParam(definesWrapperArg, 'threadCycles', 1);
 | 
					 | 
				
			||||||
    definesWrapperArg = addDefineByParam(definesWrapperArg, 'mcuClk', 1);
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function definesUserArg = parseDefinesMaskText()
 | 
					 | 
				
			||||||
    blockHandle = gcbh;
 | 
					 | 
				
			||||||
    % Получаем MaskValues и MaskNames
 | 
					 | 
				
			||||||
    maskValues = get_param(blockHandle, 'MaskValues');
 | 
					 | 
				
			||||||
    paramNames = get_param(blockHandle, 'MaskNames');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Индекс параметра userDefs
 | 
					 | 
				
			||||||
    idxUserDefs = find(strcmp(paramNames, 'userDefs'));
 | 
					 | 
				
			||||||
    definesText = maskValues{idxUserDefs}; % Текст с пользовательскими определениями
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Убираем буквальные символы \n и \r
 | 
					 | 
				
			||||||
    definesText = strrep(definesText, '\n', ' ');
 | 
					 | 
				
			||||||
    definesText = strrep(definesText, '\r', ' ');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Разбиваем по переносам строк
 | 
					 | 
				
			||||||
    lines = split(definesText, {'\n', '\r\n', '\r'});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    parts = strings(1,0); % пустой массив строк
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for k = 1:numel(lines)
 | 
					 | 
				
			||||||
        line = strtrim(lines{k});
 | 
					 | 
				
			||||||
        if isempty(line)
 | 
					 | 
				
			||||||
            continue;
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        % Разбиваем по пробелам, чтобы получить отдельные определения в строке
 | 
					 | 
				
			||||||
        tokens = split(line);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for t = 1:numel(tokens)
 | 
					 | 
				
			||||||
            token = strtrim(tokens{t});
 | 
					 | 
				
			||||||
            if isempty(token)
 | 
					 | 
				
			||||||
                continue;
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            eqIdx = strfind(token, '=');
 | 
					 | 
				
			||||||
            if isempty(eqIdx)
 | 
					 | 
				
			||||||
                % Просто ключ без значения
 | 
					 | 
				
			||||||
                parts(end+1) = sprintf('-D"%s"', token);
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
                key = strtrim(token(1:eqIdx(1)-1));
 | 
					 | 
				
			||||||
                val = strtrim(token(eqIdx(1)+1:end));
 | 
					 | 
				
			||||||
                parts(end+1) = sprintf('-D"%s__EQ__%s"', key, val);
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    definesUserArg = strjoin(parts, ' ');
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function definesWrapperArg = buildConfigDefinesString()
 | 
					 | 
				
			||||||
    blockHandle = gcbh;
 | 
					 | 
				
			||||||
    mask = Simulink.Mask.get(blockHandle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    tabName = 'configTab';  % Имя вкладки (Prompt)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    allControls = mask.getDialogControls();
 | 
					 | 
				
			||||||
    tabCtrl = find_tab_by_name(allControls, tabName);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if isempty(tabCtrl)
 | 
					 | 
				
			||||||
        error('Вкладка с названием "%s" не найдена в маске', tabName);
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
    definesWrapperArg = '';
 | 
					 | 
				
			||||||
    % Получаем все контролы внутри вкладки
 | 
					 | 
				
			||||||
    children = tabCtrl.DialogControls;
 | 
					 | 
				
			||||||
    for i = 1:numel(children)
 | 
					 | 
				
			||||||
        ctrl = children(i);
 | 
					 | 
				
			||||||
        % Получаем имя параметра из контрола
 | 
					 | 
				
			||||||
        paramName = ctrl.Name;
 | 
					 | 
				
			||||||
            try
 | 
					 | 
				
			||||||
                % Получаем объект параметра по имени
 | 
					 | 
				
			||||||
                param = mask.getParameter(paramName);
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
                % Определяем тип параметра
 | 
					 | 
				
			||||||
                switch lower(param.Type)
 | 
					 | 
				
			||||||
                    case 'checkbox'
 | 
					 | 
				
			||||||
                        definesWrapperArg = addDefineByParam(definesWrapperArg, paramName, 0);
 | 
					 | 
				
			||||||
                    case 'edit'
 | 
					 | 
				
			||||||
                        definesWrapperArg = addDefineByParam(definesWrapperArg, paramName, 1);
 | 
					 | 
				
			||||||
                    otherwise
 | 
					 | 
				
			||||||
                        % Необрабатываемые типы
 | 
					 | 
				
			||||||
                end
 | 
					 | 
				
			||||||
            catch ME
 | 
					 | 
				
			||||||
                warning('Не удалось получить параметр "%s": %s', paramName, ME.message);
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
%% PARSE FUNCTIONS
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function out = parseCellString(str)
 | 
					 | 
				
			||||||
    str = strtrim(str);
 | 
					 | 
				
			||||||
    if startsWith(str, '{') && endsWith(str, '}')
 | 
					 | 
				
			||||||
        str = str(2:end-1);
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    parts = split(str, ';');
 | 
					 | 
				
			||||||
    out = cell(numel(parts), 1);
 | 
					 | 
				
			||||||
    for i = 1:numel(parts)
 | 
					 | 
				
			||||||
        el = strtrim(parts{i});
 | 
					 | 
				
			||||||
        if startsWith(el, '''') && endsWith(el, '''')
 | 
					 | 
				
			||||||
            el = el(2:end-1);
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
        out{i} = el;
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if isempty(out) || (numel(out) == 1 && isempty(out{1}))
 | 
					 | 
				
			||||||
        out = {};
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function str = cellArrayToString(cellArray)
 | 
					 | 
				
			||||||
    quoted = cellfun(@(s) ['''' s ''''], cellArray, 'UniformOutput', false);
 | 
					 | 
				
			||||||
    str = ['{' strjoin(quoted, ';') '}'];
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function definesWrapperArg = addDefineByParam(definesWrapperArg, paramName, val_define)
 | 
					 | 
				
			||||||
    blockHandle = gcbh;
 | 
					 | 
				
			||||||
    mask = Simulink.Mask.get(blockHandle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Получаем MaskValues, MaskNames
 | 
					 | 
				
			||||||
    maskValues = get_param(blockHandle, 'MaskValues');
 | 
					 | 
				
			||||||
    paramNames = get_param(blockHandle, 'MaskNames');
 | 
					 | 
				
			||||||
    param = mask.getParameter(paramName); % для alias
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Найдём индекс нужного параметра
 | 
					 | 
				
			||||||
    idxParam = find(strcmp(paramNames, paramName), 1);
 | 
					 | 
				
			||||||
    if isempty(idxParam)
 | 
					 | 
				
			||||||
        error('Parameter "%s" not found in block mask parameters.', paramName);
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Берём alias из маски
 | 
					 | 
				
			||||||
    alias = param.Alias;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if val_define ~= 0
 | 
					 | 
				
			||||||
        % Значение параметра
 | 
					 | 
				
			||||||
        val = maskValues{idxParam};
 | 
					 | 
				
			||||||
        % Формируем define с кавычками и значением
 | 
					 | 
				
			||||||
        newDefine = ['-D"' alias '__EQ__' val '"'];
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
        if read_checkbox(paramName)
 | 
					 | 
				
			||||||
            % Формируем define с кавычками без значения
 | 
					 | 
				
			||||||
            newDefine = ['-D"' alias '"'];
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            newDefine = '';
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Добавляем новый define к существующему (string)
 | 
					 | 
				
			||||||
    if isempty(definesWrapperArg) || strlength(strtrim(definesWrapperArg)) == 0
 | 
					 | 
				
			||||||
        definesWrapperArg = newDefine;
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
        definesWrapperArg = definesWrapperArg + " " + newDefine;
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function checkbox_state = read_checkbox(checkboxName)
 | 
					 | 
				
			||||||
    maskValues = get_param(gcbh, 'MaskValues');
 | 
					 | 
				
			||||||
    paramNames = get_param(gcbh, 'MaskNames');
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    inxCheckBox = find(strcmp(paramNames, checkboxName));
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    checkbox_state_str = maskValues{inxCheckBox};
 | 
					 | 
				
			||||||
    if strcmpi(checkbox_state_str, 'on')
 | 
					 | 
				
			||||||
        checkbox_state = 1;
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
        checkbox_state = 0;
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
%% CONSOLE FUNCTIONS
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function cmdret = runBatAndShowOutput(cmd)
 | 
					 | 
				
			||||||
    import java.io.*;
 | 
					 | 
				
			||||||
    import java.lang.*;
 | 
					 | 
				
			||||||
    cmdEnglish = ['chcp 437 > nul && ' cmd];
 | 
					 | 
				
			||||||
    pb = java.lang.ProcessBuilder({'cmd.exe', '/c', cmdEnglish});
 | 
					 | 
				
			||||||
    pb.redirectErrorStream(true);
 | 
					 | 
				
			||||||
    process = pb.start();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    reader = BufferedReader(InputStreamReader(process.getInputStream()));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    cmdret = ""; % Здесь будем накапливать весь вывод
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    while true
 | 
					 | 
				
			||||||
        if reader.ready()
 | 
					 | 
				
			||||||
            line = char(reader.readLine());
 | 
					 | 
				
			||||||
            if isempty(line)
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
            cmdret = cmdret + string(line) + newline; % сохраняем вывод
 | 
					 | 
				
			||||||
            % Здесь выводим только новую строку
 | 
					 | 
				
			||||||
            safeLine = strrep(line, '''', ''''''); % Экранируем апострофы
 | 
					 | 
				
			||||||
            logWindow_append(safeLine);
 | 
					 | 
				
			||||||
            drawnow; % обновляем GUI
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            if ~process.isAlive()
 | 
					 | 
				
			||||||
                % дочитываем оставшиеся строки
 | 
					 | 
				
			||||||
                while reader.ready()
 | 
					 | 
				
			||||||
                    line = char(reader.readLine());
 | 
					 | 
				
			||||||
                    if isempty(line)
 | 
					 | 
				
			||||||
                        break;
 | 
					 | 
				
			||||||
                    end
 | 
					 | 
				
			||||||
                    cmdret = cmdret + string(line) + newline; % сохраняем вывод
 | 
					 | 
				
			||||||
                    safeLine = strrep(line, '''', '''''');
 | 
					 | 
				
			||||||
                    logWindow_append(safeLine);
 | 
					 | 
				
			||||||
                    drawnow;
 | 
					 | 
				
			||||||
                end
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
            pause(0.2);
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
    process.waitFor();
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function logWindow_append(line)
 | 
					 | 
				
			||||||
    persistent fig hEdit jScrollPane jTextArea
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if isempty(fig) || ~isvalid(fig)
 | 
					 | 
				
			||||||
        fig = figure('Name', 'Log Window', 'Position', [100 100 600 400]);
 | 
					 | 
				
			||||||
        hEdit = uicontrol('Style', 'edit', ...
 | 
					 | 
				
			||||||
            'Max', 2, 'Min', 0, ...
 | 
					 | 
				
			||||||
            'Enable', 'on', ...
 | 
					 | 
				
			||||||
            'FontName', 'Courier New', ...
 | 
					 | 
				
			||||||
            'Position', [10 10 580 380], ...
 | 
					 | 
				
			||||||
            'HorizontalAlignment', 'left', ...
 | 
					 | 
				
			||||||
            'BackgroundColor', 'white', ...
 | 
					 | 
				
			||||||
            'Tag', 'LogWindowFigure');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        jScrollPane = findjobj(hEdit);                  % JScrollPane
 | 
					 | 
				
			||||||
        jTextArea = jScrollPane.getViewport.getView;   % JTextArea внутри JScrollPane
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    oldText = get(hEdit, 'String');
 | 
					 | 
				
			||||||
    if ischar(oldText)
 | 
					 | 
				
			||||||
        oldText = {oldText};
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    set(hEdit, 'String', [oldText; {line}]);
 | 
					 | 
				
			||||||
    drawnow;
 | 
					 | 
				
			||||||
    % Автоскролл вниз:
 | 
					 | 
				
			||||||
    jTextArea.setCaretPosition(jTextArea.getDocument.getLength);
 | 
					 | 
				
			||||||
    drawnow;
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
%% READ CONFIGS
 | 
					 | 
				
			||||||
function config = read_periph_config()
 | 
					 | 
				
			||||||
    jsonText = fileread('periph_config.json');
 | 
					 | 
				
			||||||
    config = jsondecode(jsonText);
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function write_periph_config(config)
 | 
					 | 
				
			||||||
    jsonText = jsonencode(config, 'PrettyPrint', true);
 | 
					 | 
				
			||||||
    fid = fopen('periph_config.json', 'w');
 | 
					 | 
				
			||||||
    if fid == -1
 | 
					 | 
				
			||||||
        error('Не удалось открыть файл periph_config.json для записи.');
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
    fwrite(fid, jsonText, 'char');
 | 
					 | 
				
			||||||
    fclose(fid);
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
%% CONFIG MASK TOOLS
 | 
					 | 
				
			||||||
function update_mask_from_config(blockPath, config)
 | 
					 | 
				
			||||||
    blockPath = [blockPath '/MCU'];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Проверяем, была ли маска открыта
 | 
					 | 
				
			||||||
    wasOpen = isMaskDialogOpen(blockPath);
 | 
					 | 
				
			||||||
    close_system(blockPath, 0);
 | 
					 | 
				
			||||||
    mask = Simulink.Mask.get(blockPath);
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    tableNames = {'incTable', 'srcTable'};
 | 
					 | 
				
			||||||
    columns_backup = clear_tables(blockPath, tableNames);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    containerName = 'configTabAll';
 | 
					 | 
				
			||||||
    clear_all_from_container(mask, containerName);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Ищем контейнер, в который будем добавлять вкладки
 | 
					 | 
				
			||||||
    allControls = mask.getDialogControls();
 | 
					 | 
				
			||||||
    container = find_container_by_name(allControls, containerName);
 | 
					 | 
				
			||||||
    if isempty(container)
 | 
					 | 
				
			||||||
        error('Контейнер "%s" не найден в маске.', containerName);
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Проходим по каждому модулю (ADC, TIM...)
 | 
					 | 
				
			||||||
    periphs = fieldnames(config);
 | 
					 | 
				
			||||||
    for i = 1:numel(periphs)
 | 
					 | 
				
			||||||
        periph = periphs{i};
 | 
					 | 
				
			||||||
        defines = config.(periph).Defines;
 | 
					 | 
				
			||||||
        defNames = fieldnames(defines);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        % Создаём вкладку для модуля
 | 
					 | 
				
			||||||
        tabCtrl = container.addDialogControl('tab', periph);
 | 
					 | 
				
			||||||
        tabCtrl.Prompt = [periph ' Config'];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for j = 1:numel(defNames)
 | 
					 | 
				
			||||||
            defPrompt = defNames{j};
 | 
					 | 
				
			||||||
            def = defines.(defPrompt);
 | 
					 | 
				
			||||||
            prompt = def.Prompt;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            % Только checkbox и edit
 | 
					 | 
				
			||||||
            switch lower(def.Type)
 | 
					 | 
				
			||||||
                case 'checkbox'
 | 
					 | 
				
			||||||
                    paramType = 'checkbox';
 | 
					 | 
				
			||||||
                case 'edit'
 | 
					 | 
				
			||||||
                    paramType = 'edit';
 | 
					 | 
				
			||||||
                otherwise
 | 
					 | 
				
			||||||
                    continue;
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            paramName = matlab.lang.makeValidName(defPrompt);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            % Преобразуем значение по типу
 | 
					 | 
				
			||||||
            val = def.Default;
 | 
					 | 
				
			||||||
            if islogical(val)
 | 
					 | 
				
			||||||
                if val
 | 
					 | 
				
			||||||
                    valStr = 'on';
 | 
					 | 
				
			||||||
                else
 | 
					 | 
				
			||||||
                    valStr = 'off';
 | 
					 | 
				
			||||||
                end
 | 
					 | 
				
			||||||
            elseif isnumeric(val)
 | 
					 | 
				
			||||||
                valStr = num2str(val);
 | 
					 | 
				
			||||||
            elseif ischar(val)
 | 
					 | 
				
			||||||
                valStr = val;
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
                error('Unsupported default value type for %s.%s', periph, defPrompt);
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            % Добавляем параметр в соответствующую вкладку
 | 
					 | 
				
			||||||
            param = mask.addParameter( ...
 | 
					 | 
				
			||||||
                'Type', paramType, ...
 | 
					 | 
				
			||||||
                'Prompt', prompt, ...
 | 
					 | 
				
			||||||
                'Name', paramName, ...
 | 
					 | 
				
			||||||
                'Value', valStr, ...
 | 
					 | 
				
			||||||
                'Container', periph ...
 | 
					 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            param.Alias = def.Def;
 | 
					 | 
				
			||||||
            if def.NewRow
 | 
					 | 
				
			||||||
                row_param = 'new';
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
                row_param = 'current';
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
            param.DialogControl.Row = row_param;
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Восстанавливаем таблицы
 | 
					 | 
				
			||||||
    restore_tables(blockPath, tableNames, columns_backup);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Повторно открываем маску, если она была открыта
 | 
					 | 
				
			||||||
    if wasOpen
 | 
					 | 
				
			||||||
        open_system(blockPath, 'mask');
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function config = update_config_from_mask(blockPath, config)
 | 
					 | 
				
			||||||
    blockPath = [blockPath '/MCU'];
 | 
					 | 
				
			||||||
    mask = Simulink.Mask.get(blockPath);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    periphs = fieldnames(config);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for i = 1:numel(periphs)
 | 
					 | 
				
			||||||
        periph = periphs{i};
 | 
					 | 
				
			||||||
        defines = config.(periph).Defines;
 | 
					 | 
				
			||||||
        defNames = fieldnames(defines);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for j = 1:numel(defNames)
 | 
					 | 
				
			||||||
            defPrompt = defNames{j};
 | 
					 | 
				
			||||||
            paramName = matlab.lang.makeValidName(defPrompt);
 | 
					 | 
				
			||||||
            param = mask.getParameter(paramName);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            % Получаем значение из маски и сохраняем в конфиг
 | 
					 | 
				
			||||||
            valStr = param.Value;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            % Преобразуем строку в соответствующий тип
 | 
					 | 
				
			||||||
            if strcmpi(defines.(defPrompt).Type, 'checkbox')
 | 
					 | 
				
			||||||
                config.(periph).Defines.(defPrompt).Default = strcmpi(valStr, 'on');
 | 
					 | 
				
			||||||
            elseif strcmpi(defines.(defPrompt).Type, 'edit')
 | 
					 | 
				
			||||||
                valNum = str2double(valStr);
 | 
					 | 
				
			||||||
                if isnan(valNum)
 | 
					 | 
				
			||||||
                    config.(periph).Defines.(defPrompt).Default = valStr;
 | 
					 | 
				
			||||||
                else
 | 
					 | 
				
			||||||
                    config.(periph).Defines.(defPrompt).Default = valNum;
 | 
					 | 
				
			||||||
                end
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function clear_all_from_container(mask, containerName)
 | 
					 | 
				
			||||||
    allControls = mask.getDialogControls();
 | 
					 | 
				
			||||||
    container = find_container_by_name(allControls, containerName);
 | 
					 | 
				
			||||||
    if isempty(container)
 | 
					 | 
				
			||||||
        warning('Контейнер "%s" не найден.', containerName);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Рекурсивно собрать все параметры (не вкладки)
 | 
					 | 
				
			||||||
    paramsToDelete = collect_all_parameters(container);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Удаляем все параметры
 | 
					 | 
				
			||||||
    for i = 1:numel(paramsToDelete)
 | 
					 | 
				
			||||||
        try
 | 
					 | 
				
			||||||
            mask.removeParameter(paramsToDelete{i});
 | 
					 | 
				
			||||||
        catch
 | 
					 | 
				
			||||||
            warning('Не удалось удалить параметр %s', paramsToDelete{i});
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Рекурсивно удалить все вкладки внутри контейнера
 | 
					 | 
				
			||||||
    delete_all_tabs(mask, container);
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function params = collect_all_parameters(container)
 | 
					 | 
				
			||||||
    params = {};
 | 
					 | 
				
			||||||
    children = container.DialogControls;
 | 
					 | 
				
			||||||
    for i = 1:numel(children)
 | 
					 | 
				
			||||||
        ctrl = children(i);
 | 
					 | 
				
			||||||
        if isa(ctrl, 'Simulink.dialog.Tab')
 | 
					 | 
				
			||||||
            % Если вкладка — рекурсивно собираем параметры внутри неё
 | 
					 | 
				
			||||||
            params = [params, collect_all_parameters(ctrl)];
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            % Иначе это параметр — добавляем имя
 | 
					 | 
				
			||||||
            params{end+1} = ctrl.Name; %#ok<AGROW>
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function delete_all_tabs(mask, container)
 | 
					 | 
				
			||||||
    children = container.DialogControls;
 | 
					 | 
				
			||||||
    % Идём в обратном порядке, чтобы безопасно удалять
 | 
					 | 
				
			||||||
    for i = numel(children):-1:1
 | 
					 | 
				
			||||||
        ctrl = children(i);
 | 
					 | 
				
			||||||
        if isa(ctrl, 'Simulink.dialog.Tab')
 | 
					 | 
				
			||||||
            % Сначала рекурсивно удаляем вкладки внутри текущей вкладки
 | 
					 | 
				
			||||||
            delete_all_tabs(mask, ctrl);
 | 
					 | 
				
			||||||
            try
 | 
					 | 
				
			||||||
                container.removeDialogControl(ctrl.Name);
 | 
					 | 
				
			||||||
            catch ME
 | 
					 | 
				
			||||||
                warning('Не удалось удалить вкладку %s: %s', ctrl.Name, ME.message);
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function isOpen = isMaskDialogOpen(blockPath)
 | 
					 | 
				
			||||||
    isOpen = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    try
 | 
					 | 
				
			||||||
        % Получаем имя блока
 | 
					 | 
				
			||||||
        blockName = get_param(blockPath, 'Name');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        % Получаем список окон MATLAB GUI
 | 
					 | 
				
			||||||
        jWindows = java.awt.Window.getWindows();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for i = 1:numel(jWindows)
 | 
					 | 
				
			||||||
            win = jWindows(i);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            % Проверка, что окно видимое и активно
 | 
					 | 
				
			||||||
            if win.isShowing()
 | 
					 | 
				
			||||||
                try
 | 
					 | 
				
			||||||
                    title = char(win.getTitle());
 | 
					 | 
				
			||||||
                    % Проверка по ключевому слову, соответствующему заголовку маски
 | 
					 | 
				
			||||||
                    if contains(title, ['Mask Editor: ' blockName]) || ...
 | 
					 | 
				
			||||||
                       contains(title, ['Mask: ' blockName]) || ...
 | 
					 | 
				
			||||||
                       contains(title, blockName)
 | 
					 | 
				
			||||||
                        isOpen = true;
 | 
					 | 
				
			||||||
                        return;
 | 
					 | 
				
			||||||
                    end
 | 
					 | 
				
			||||||
                catch
 | 
					 | 
				
			||||||
                    % Окно не имеет заголовка — пропускаем
 | 
					 | 
				
			||||||
                end
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    catch
 | 
					 | 
				
			||||||
        isOpen = false;
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function column_titles = clear_tables(block, table_names)
 | 
					 | 
				
			||||||
    % Очищает столбцы в каждой таблице из массива имен table_names
 | 
					 | 
				
			||||||
    % Возвращает cell-массив с названиями первых столбцов каждой таблицы
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    % Получить объект маски блока
 | 
					 | 
				
			||||||
    maskObj = Simulink.Mask.get(block);
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    % Инициализировать cell-массив для хранения названий столбцов
 | 
					 | 
				
			||||||
    column_titles = cell(size(table_names));
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    for k = 1:numel(table_names)
 | 
					 | 
				
			||||||
        table_name = table_names{k};
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        % Получить объект управления таблицей
 | 
					 | 
				
			||||||
        tableControl = maskObj.getDialogControl(table_name);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        % Получить количество столбцов
 | 
					 | 
				
			||||||
        nCols = tableControl.getNumberOfColumns;
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        if nCols > 0
 | 
					 | 
				
			||||||
            % Получить первый столбец (который будем удалять)
 | 
					 | 
				
			||||||
            column = tableControl.getColumn(1);
 | 
					 | 
				
			||||||
            column_titles{k} = column.Name;
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            % Удаляем все столбцы
 | 
					 | 
				
			||||||
            % Важно: при удалении столбцов индексы меняются, 
 | 
					 | 
				
			||||||
            % поэтому удаляем всегда первый столбец nCols раз
 | 
					 | 
				
			||||||
            for i = 1:nCols
 | 
					 | 
				
			||||||
                tableControl.removeColumn(1);
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            % Если столбцов нет, возвращаем пустую строку
 | 
					 | 
				
			||||||
            column_titles{k} = '';
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function restore_tables(block, table_names, column_titles)
 | 
					 | 
				
			||||||
    % Восстанавливает первый столбец в каждой таблице из массива имен
 | 
					 | 
				
			||||||
    % Использует массив column_titles для установки имени столбца
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    % Получить объект маски блока
 | 
					 | 
				
			||||||
    maskObj = Simulink.Mask.get(block);
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    for k = 1:numel(table_names)
 | 
					 | 
				
			||||||
        table_name = table_names{k};
 | 
					 | 
				
			||||||
        title = column_titles{k};
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        % Получить объект управления таблицей
 | 
					 | 
				
			||||||
        tableControl = maskObj.getDialogControl(table_name);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        % Добавить новый столбец
 | 
					 | 
				
			||||||
        column = tableControl.addColumn(Name='title', Type='edit');
 | 
					 | 
				
			||||||
        column.Name = title;
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function tab = find_tab_by_name(controls, targetName)
 | 
					 | 
				
			||||||
    tab = [];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for i = 1:numel(controls)
 | 
					 | 
				
			||||||
        ctrl = controls(i);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        % Проверяем, вкладка ли это и совпадает ли имя
 | 
					 | 
				
			||||||
        if isa(ctrl, 'Simulink.dialog.Tab') && strcmp(ctrl.Name, targetName)
 | 
					 | 
				
			||||||
            tab = ctrl;
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        % Если это контейнер — обходим его детей
 | 
					 | 
				
			||||||
        children = get_children(ctrl);
 | 
					 | 
				
			||||||
        if ~isempty(children)
 | 
					 | 
				
			||||||
            tab = find_tab_by_name(children, targetName);
 | 
					 | 
				
			||||||
            if ~isempty(tab)
 | 
					 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function container = find_container_by_name(controls, targetName)
 | 
					 | 
				
			||||||
    container = [];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for i = 1:numel(controls)
 | 
					 | 
				
			||||||
        ctrl = controls(i);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        % Проверяем, контейнер ли это и совпадает ли имя
 | 
					 | 
				
			||||||
        if isa(ctrl, 'Simulink.dialog.Container') && strcmp(ctrl.Name, targetName)
 | 
					 | 
				
			||||||
            container = ctrl;
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        % Если это вложенный контрол — обходим его детей
 | 
					 | 
				
			||||||
        children = get_children(ctrl);
 | 
					 | 
				
			||||||
        if ~isempty(children)
 | 
					 | 
				
			||||||
            container = find_container_by_name(children, targetName);
 | 
					 | 
				
			||||||
            if ~isempty(container)
 | 
					 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function children = get_children(ctrl)
 | 
					 | 
				
			||||||
    if isprop(ctrl, 'DialogControls')
 | 
					 | 
				
			||||||
        children = ctrl.DialogControls;
 | 
					 | 
				
			||||||
    elseif isprop(ctrl, 'Controls')
 | 
					 | 
				
			||||||
        children = ctrl.Controls;
 | 
					 | 
				
			||||||
    elseif isprop(ctrl, 'Children')
 | 
					 | 
				
			||||||
        children = ctrl.Children;
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
        children = [];
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
@ -11,33 +11,37 @@
 | 
				
			|||||||
:: %4 — режим компиляции (debug/release)
 | 
					:: %4 — режим компиляции (debug/release)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
:: Сохраняем как переменные
 | 
					:: Сохраняем как переменные
 | 
				
			||||||
set includes_USER=%~1
 | 
					set filename=%~1
 | 
				
			||||||
set code_USER=%~2
 | 
					set includes_USER=%~2
 | 
				
			||||||
set defines_USER=%~3
 | 
					set code_USER=%~3
 | 
				
			||||||
set compil_mode=%~4
 | 
					set defines_USER=%~4
 | 
				
			||||||
 | 
					set defines_CONFIG=%~5
 | 
				
			||||||
 | 
					set compil_mode=%~6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
:: Заменяем __EQ__ на =
 | 
					:: Заменяем __EQ__ на =
 | 
				
			||||||
set defines_USER=%defines_USER:__EQ__==%
 | 
					set defines_USER=%defines_USER:__EQ__==%
 | 
				
			||||||
 | 
					set defines_CONFIG=%defines_CONFIG:__EQ__==%
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set defines_WRAPPER=-D"MATLAB"^ -D"__sizeof_ptr=8"
 | 
					set defines_WRAPPER=-D"MATLAB"^ -D"__sizeof_ptr=8"
 | 
				
			||||||
 | 
					 | 
				
			||||||
:: -------------------------USERS PATHS AND CODE---------------------------
 | 
					:: -------------------------USERS PATHS AND CODE---------------------------
 | 
				
			||||||
::-------------------------------------------------------------------------
 | 
					::-------------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
:: -----------------------MCU LIBRARIES & SIMULATOR------------------------
 | 
					:: -------------------------WRAPPER PATHS AND CODE---------------------------
 | 
				
			||||||
:: -----MCU LIBRARIES STUFF----
 | 
					:: оболочка, которая будет моделировать работу МК в симулинке
 | 
				
			||||||
:: заголовочные файлы
 | 
					set includes_WRAPPER=-I"."^
 | 
				
			||||||
set includes_MCU= -I".\MCU_STM32F1xx_Matlab"^
 | 
					 -I".\MCU_Wrapper"^
 | 
				
			||||||
 -I".\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_SIMULINK"^
 | 
					 -I".\app_wrapper"
 | 
				
			||||||
 -I".\MCU_STM32F1xx_Matlab\Drivers\CMSIS"^
 | 
					
 | 
				
			||||||
 -I".\MCU_STM32F1xx_Matlab\Drivers\CMSIS\Device\STM32F1xx"^
 | 
					set code_WRAPPER= .\MCU_Wrapper\MCU.c^
 | 
				
			||||||
 -I".\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_HAL_Driver\Inc"^
 | 
					 .\MCU_Wrapper\mcu_wrapper.c^
 | 
				
			||||||
 -I".\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_HAL_Driver\Inc\Legacy"
 | 
					 .\app_wrapper\app_init.c^
 | 
				
			||||||
  
 | 
					 .\app_wrapper\app_io.c^
 | 
				
			||||||
:: код библиотек МК, переделанный для матлаб
 | 
					 .\app_wrapper\app_wrapper.c
 | 
				
			||||||
set code_MCU= .\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc.c^
 | 
					
 | 
				
			||||||
 | 
					:: PERIPH BAT START
 | 
				
			||||||
 | 
					set code_PERIPH=.\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc.c^
 | 
				
			||||||
 .\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio.c^
 | 
					 .\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_gpio.c^
 | 
				
			||||||
 .\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_pwr.c^
 | 
					 .\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_pwr.c^
 | 
				
			||||||
 .\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_cortex.c^
 | 
					 .\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_cortex.c^
 | 
				
			||||||
@ -47,64 +51,56 @@ set code_MCU= .\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_
 | 
				
			|||||||
 .\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_tim.c^
 | 
					 .\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_tim.c^
 | 
				
			||||||
 .\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_tim_ex.c^
 | 
					 .\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_tim_ex.c^
 | 
				
			||||||
 .\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_dma.c^
 | 
					 .\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_dma.c^
 | 
				
			||||||
 .\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_exti.c
 | 
					 .\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_exti.c^
 | 
				
			||||||
 | 
					 .\MCU_STM32F1xx_Matlab\stm32f1xx_matlab_conf.c^
 | 
				
			||||||
:: .\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash_ramfunc.c^
 | 
					 | 
				
			||||||
:: .\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash.c^
 | 
					 | 
				
			||||||
:: .\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_flash_ex.c^
 | 
					 | 
				
			||||||
:: .\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_HAL_Driver\Src\stm32f1xx_hal_rcc_ex.c^
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
:: --------MCU SIMULATOR-------
 | 
					 | 
				
			||||||
:: код, которая будет симулировать перефирию МК в симулинке
 | 
					 | 
				
			||||||
set code_MCU_Sim= .\MCU_STM32F1xx_Matlab\stm32f1xx_matlab_conf.c^
 | 
					 | 
				
			||||||
 .\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_SIMULINK\stm32f1xx_matlab_gpio.c^
 | 
					 .\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_SIMULINK\stm32f1xx_matlab_gpio.c^
 | 
				
			||||||
 .\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_SIMULINK\stm32f1xx_matlab_tim.c^
 | 
					 .\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_SIMULINK\stm32f1xx_matlab_tim.c^
 | 
				
			||||||
 .\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_SIMULINK\stm32f1xx_periph_registers.c 
 | 
					 .\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_SIMULINK\stm32f1xx_periph_registers.c
 | 
				
			||||||
::-------------------------------------------------------------------------
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set includes_PERIPH=-I".\MCU_STM32F1xx_Matlab"^
 | 
				
			||||||
:: -------------------------WRAPPER PATHS AND CODE---------------------------
 | 
					 -I".\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_SIMULINK"^
 | 
				
			||||||
:: оболочка, которая будет моделировать работу МК в симулинке
 | 
					 -I".\MCU_STM32F1xx_Matlab\Drivers\CMSIS"^
 | 
				
			||||||
set includes_WRAPPER= -I".\MCU_Wrapper"
 | 
					 -I".\MCU_STM32F1xx_Matlab\Drivers\CMSIS\Device\STM32F1xx"^
 | 
				
			||||||
set code_WRAPPER= .\MCU_Wrapper\MCU.c^
 | 
					 -I".\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_HAL_Driver\Inc"^
 | 
				
			||||||
 .\MCU_Wrapper\mcu_wrapper.c^
 | 
					 -I".\MCU_STM32F1xx_Matlab\Drivers\STM32F1xx_HAL_Driver\Inc\Legacy"
 | 
				
			||||||
 .\MCU_Wrapper\app_wrapper.c
 | 
					:: PERIPH BAT END
 | 
				
			||||||
::-------------------------------------------------------------------------
 | 
					::-------------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
:: ---------------------SET PARAMS FOR MEX COMPILING-----------------------
 | 
					:: ---------------------SET PARAMS FOR MEX COMPILING-----------------------
 | 
				
			||||||
:: --------ALL INCLUDES--------
 | 
					:: -------------ALL------------
 | 
				
			||||||
set includes= %includes_USER% %includes_MCU% %includes_WRAPPER%
 | 
					set includes= %includes_WRAPPER% %includes_PERIPH% %includes_USER%
 | 
				
			||||||
set codes= %code_WRAPPER% %code_USER% %code_MCU% %code_MCU_Sim%
 | 
					set codes= %code_WRAPPER% %code_USER% %code_PERIPH%
 | 
				
			||||||
set defines= %defines_USER% %defines_WRAPPER%
 | 
					set defines= %defines_WRAPPER% %defines_CONFIG% %defines_USER%
 | 
				
			||||||
:: -------OUTPUT FOLDER--------
 | 
					:: -------OUTPUT FOLDER--------
 | 
				
			||||||
set output= -outdir "."
 | 
					set output= -outdir "." -output %filename%
 | 
				
			||||||
 | 
					
 | 
				
			||||||
:: если нужен дебаг, до запускаем run mex с припиской debug
 | 
					:: если нужен дебаг, до запускаем run_mex с припиской debug
 | 
				
			||||||
IF %compil_mode%==[debug] (set debug= -g)
 | 
					IF %compil_mode%==debug (set debug= -g)
 | 
				
			||||||
::-------------------------------------------------------------------------
 | 
					::-------------------------------------------------------------------------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
::------START COMPILING-------    
 | 
					::------START COMPILING-------    
 | 
				
			||||||
if "%5"=="echo_enable" (
 | 
					if "%7"=="echo_enable" (
 | 
				
			||||||
    echo Compiling...
 | 
					    echo Compiling...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    echo ===========================
 | 
					    echo ===========================
 | 
				
			||||||
    echo INCLUDES:
 | 
					    echo =========INCLUDES==========
 | 
				
			||||||
    echo USER:
 | 
					    echo USER:
 | 
				
			||||||
    for %%f in (%includes_USER%) do (
 | 
					    for %%f in (%includes_USER%) do (
 | 
				
			||||||
        echo   %%f
 | 
					        echo   %%f
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    echo INTERNAL:
 | 
					    echo INTERNAL:
 | 
				
			||||||
    for %%f in (%includes_MCU%) do (
 | 
					    for %%f in (%includes_WRAPPER%) do (
 | 
				
			||||||
        echo   %%f
 | 
					        echo   %%f
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    for %%f in (%includes_WRAPPER%) do (
 | 
					    echo PERIPH:
 | 
				
			||||||
 | 
					    for %%f in (%includes_PERIPH%) do (
 | 
				
			||||||
        echo   %%f
 | 
					        echo   %%f
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    echo ===========================
 | 
					    echo ===========================
 | 
				
			||||||
    echo SOURCES:
 | 
					    echo ==========SOURCES==========
 | 
				
			||||||
    echo USER:
 | 
					    echo USER:
 | 
				
			||||||
    for %%f in (%code_USER%) do (
 | 
					    for %%f in (%code_USER%) do (
 | 
				
			||||||
        echo   %%f
 | 
					        echo   %%f
 | 
				
			||||||
@ -113,19 +109,21 @@ if "%5"=="echo_enable" (
 | 
				
			|||||||
    for %%f in (%code_WRAPPER%) do (
 | 
					    for %%f in (%code_WRAPPER%) do (
 | 
				
			||||||
        echo   %%f
 | 
					        echo   %%f
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    for %%f in (%code_MCU_Sim%) do (
 | 
					    echo PERIPH:
 | 
				
			||||||
        echo   %%f
 | 
					    for %%f in (%code_PERIPH%) do (
 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
    for %%f in (%code_MCU%) do (
 | 
					 | 
				
			||||||
        echo   %%f
 | 
					        echo   %%f
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    echo ===========================
 | 
					    echo ===========================
 | 
				
			||||||
    echo DEFINES:
 | 
					    echo ==========DEFINES==========
 | 
				
			||||||
    echo USER:
 | 
					    echo USER:
 | 
				
			||||||
    for %%d in (%defines_USER%) do (
 | 
					    for %%d in (%defines_USER%) do (
 | 
				
			||||||
        echo   %%d
 | 
					        echo   %%d
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					    echo CONFIG:
 | 
				
			||||||
 | 
					    for %%f in (%defines_CONFIG%) do (
 | 
				
			||||||
 | 
					        echo   %%f
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
    echo INTERNAL:
 | 
					    echo INTERNAL:
 | 
				
			||||||
    for %%f in (%defines_WRAPPER%) do (
 | 
					    for %%f in (%defines_WRAPPER%) do (
 | 
				
			||||||
        echo   %%f
 | 
					        echo   %%f
 | 
				
			||||||
@ -134,6 +132,6 @@ if "%5"=="echo_enable" (
 | 
				
			|||||||
echo ===========================
 | 
					echo ===========================
 | 
				
			||||||
echo MODE: %compil_mode%
 | 
					echo MODE: %compil_mode%
 | 
				
			||||||
echo ===========================
 | 
					echo ===========================
 | 
				
			||||||
 | 
					 | 
				
			||||||
mex %output% %defines% %includes% %codes% %debug%
 | 
					mex %output% %defines% %includes% %codes% %debug%
 | 
				
			||||||
echo %DATE% %TIME%
 | 
					echo %DATE% %TIME%
 | 
				
			||||||
 | 
					exit /b %ERRORLEVEL%
 | 
				
			||||||
							
								
								
									
										10
									
								
								app_wrapper/app_configs.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								app_wrapper/app_configs.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					**************************************************************************
 | 
				
			||||||
 | 
					* @file app_config.h
 | 
				
			||||||
 | 
					* @brief Заголовочный файл для пользовательских конфигураций.
 | 
				
			||||||
 | 
					**************************************************************************/
 | 
				
			||||||
 | 
					#ifndef _APP_CONFIG
 | 
				
			||||||
 | 
					#define _APP_CONFIG
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif //_APP_CONFIG
 | 
				
			||||||
							
								
								
									
										17
									
								
								app_wrapper/app_includes.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								app_wrapper/app_includes.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					**************************************************************************
 | 
				
			||||||
 | 
					* @file app_includes.h
 | 
				
			||||||
 | 
					* @brief Заголовочный файл для подключаения заголовочных файлов программы МК.
 | 
				
			||||||
 | 
					**************************************************************************/
 | 
				
			||||||
 | 
					#ifndef _APP_INCLUDES_H_
 | 
				
			||||||
 | 
					#define _APP_INCLUDES_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "app_configs.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// INCLUDES START
 | 
				
			||||||
 | 
					// Инклюды для доступа к коду МК в коде оболочке
 | 
				
			||||||
 | 
					#include "upp.h"
 | 
				
			||||||
 | 
					#include "main.h"
 | 
				
			||||||
 | 
					// INCLUDES END
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif //_APP_INCLUDES_H_
 | 
				
			||||||
							
								
								
									
										38
									
								
								app_wrapper/app_init.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								app_wrapper/app_init.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					**************************************************************************
 | 
				
			||||||
 | 
					* @file app_init.h
 | 
				
			||||||
 | 
					* @brief Файл с функцией инициализации программы МК @ref app_init.
 | 
				
			||||||
 | 
					**************************************************************************/
 | 
				
			||||||
 | 
					#include "mcu_wrapper_conf.h"
 | 
				
			||||||
 | 
					#include "app_wrapper.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					  * @brief Функция для инициализации приложения МК
 | 
				
			||||||
 | 
					  * @details Используется в случае симуляции без отдельного потока для main().
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					void app_init(void) {
 | 
				
			||||||
 | 
					// USER APP INIT START
 | 
				
			||||||
 | 
					// Код для инициализации приложения МК
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Вызов разных функций в случае, 
 | 
				
			||||||
 | 
					// если не используется отдельный поток для main().
 | 
				
			||||||
 | 
					HAL_Init();
 | 
				
			||||||
 | 
					MX_GPIO_Init();
 | 
				
			||||||
 | 
					MX_TIM2_Init();
 | 
				
			||||||
 | 
					upp_init();
 | 
				
			||||||
 | 
					// USER APP INIT END
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					  * @brief Функция для деинициализации приложения МК
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					void app_deinit(void) {
 | 
				
			||||||
 | 
					// USER APP DEINIT START
 | 
				
			||||||
 | 
					// Код для деинициализации приложения МК
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Структуры, переменные и так далее, которые надо очистить,
 | 
				
			||||||
 | 
					// для повторного запуска симуляции.
 | 
				
			||||||
 | 
					deInitialize_MCU();
 | 
				
			||||||
 | 
					// USER APP DEINIT END
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										118
									
								
								app_wrapper/app_io.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								app_wrapper/app_io.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,118 @@
 | 
				
			|||||||
 | 
					/**
 | 
				
			||||||
 | 
					**************************************************************************
 | 
				
			||||||
 | 
					* @file app_init.h
 | 
				
			||||||
 | 
					* @brief Файл с функциями записи входов/выходов программы МК @ref app_init.
 | 
				
			||||||
 | 
					**************************************************************************/
 | 
				
			||||||
 | 
					#include "mcu_wrapper_conf.h"
 | 
				
			||||||
 | 
					#include "app_wrapper.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					  * @brief Функция для записи входов в приложение МК
 | 
				
			||||||
 | 
					  * @param u - массив входных значений
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					void app_readInputs(const real_T* Buffer) {
 | 
				
			||||||
 | 
					// USER APP INPUT START
 | 
				
			||||||
 | 
					// Код для записи считывания входов из IO буфера
 | 
				
			||||||
 | 
					// Буфер в начале хранит входные порты S-Function, далее идут выходные порты:
 | 
				
			||||||
 | 
					// Buffer[0:15] - входной 1 порт, Buffer[16:31] - входной 2 порт, 
 | 
				
			||||||
 | 
					// Buffer[32:47] - выходной 1 порт, Buffer[48:63] - выходной 2 порт
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Note: используте для чтения:
 | 
				
			||||||
 | 
					//    val = ReadInputArray(arr_ind, val_ind)
 | 
				
			||||||
 | 
					// Пример:
 | 
				
			||||||
 | 
					// // запись в второй элемент первого массива
 | 
				
			||||||
 | 
					// app_variable = ReadInputArray(0, 1);
 | 
				
			||||||
 | 
					// // чтение из IO буфера напрямую
 | 
				
			||||||
 | 
					// app_variable_2 = Buffer[10];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define detect_front(_in_numb_, _var_, _val_) {                 \
 | 
				
			||||||
 | 
					if ((Buffer[_in_numb_] > 0.5) && (prev_in[_in_numb_] <= 0.5))   \
 | 
				
			||||||
 | 
					{                                                               \
 | 
				
			||||||
 | 
					    _var_ = _val_;                                              \
 | 
				
			||||||
 | 
					} }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define detect_rise(_in_numb_, _var_, _val_) {                  \
 | 
				
			||||||
 | 
					if ((Buffer[_in_numb_] < 0.5) && (prev_in[_in_numb_] >= 0.5))   \
 | 
				
			||||||
 | 
					{                                                               \
 | 
				
			||||||
 | 
					    _var_ = _val_;                                              \
 | 
				
			||||||
 | 
					} }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    static real_T prev_in[TOTAL_IN_SIZE];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    detect_front(0, phase_A.zc_detector.f.EXTIZeroCrossDetected, 1);
 | 
				
			||||||
 | 
					    detect_rise(0, phase_A.zc_detector.f.EXTIZeroCrossDetected, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    detect_front(1, phase_B.zc_detector.f.EXTIZeroCrossDetected, 1);
 | 
				
			||||||
 | 
					    detect_rise(1, phase_B.zc_detector.f.EXTIZeroCrossDetected, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    detect_front(2, phase_C.zc_detector.f.EXTIZeroCrossDetected, 1);
 | 
				
			||||||
 | 
					    detect_rise(2, phase_C.zc_detector.f.EXTIZeroCrossDetected, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    detect_front(3, Upp.GoSafe, 1);
 | 
				
			||||||
 | 
					    detect_rise(3, Upp.GoSafe, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    detect_front(4, Upp.Prepare, 1);
 | 
				
			||||||
 | 
					    detect_rise(4, Upp.Prepare, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    detect_front(5, Upp.ForceStop, 1);
 | 
				
			||||||
 | 
					    detect_rise(5, Upp.ForceStop, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    detect_front(6, Upp.ForceDisconnect, 1);
 | 
				
			||||||
 | 
					    detect_rise(6, Upp.ForceDisconnect, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Upp.sine_freq = Buffer[7];
 | 
				
			||||||
 | 
					    Upp.Duration = Buffer[8];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (int i = 0; i < TOTAL_IN_SIZE; i++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        prev_in[i] = Buffer[i];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					// USER APP INPUT END
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					  * @brief Функция для записи выходов приложения МК
 | 
				
			||||||
 | 
					  * @param xD - массив буффера выходов(дискретных выходов)
 | 
				
			||||||
 | 
					  * @details Используте WriteOutputArray(val, arr_ind, val_ind) для записи
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					void app_writeOutputBuffer(real_T* Buffer) {
 | 
				
			||||||
 | 
					// USER APP OUTPUT START
 | 
				
			||||||
 | 
					// Код для записи выходов в IO буфер
 | 
				
			||||||
 | 
					// Буфер в начале хранит входные порты S-Function, далее идут выходные порты:
 | 
				
			||||||
 | 
					// Buffer[0:15] - входной 1 порт, Buffer[16:31] - входной 2 порт, 
 | 
				
			||||||
 | 
					// Buffer[32:47] - выходной 1 порт, Buffer[48:63] - выходной 2 порт
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Note: используте для записи:
 | 
				
			||||||
 | 
					//    WriteOutputArray(val, arr_ind, val_ind)
 | 
				
			||||||
 | 
					// Пример:
 | 
				
			||||||
 | 
					// // запись в второй элемент первого массива
 | 
				
			||||||
 | 
					// WriteOutputArray(app_variable, 0, 1);
 | 
				
			||||||
 | 
					// // запись в IO буфер напрямую
 | 
				
			||||||
 | 
					// Buffer[XD_OUTPUT_START + 10] = app_variable_2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (int i = 0; i < 16; i++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if (GPIOA->ODR & (1 << i))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            WriteOutputArray(1, 0, i);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (GPIOB->ODR & (1 << i))
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            WriteOutputArray(1, 1, i);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int var = phase_A.ctrl.angle.delay_us;
 | 
				
			||||||
 | 
					WriteOutputArray(var, 2, 0);
 | 
				
			||||||
 | 
					var = (uint16_t)((uint16_t)TIMER->CNT - phase_A.ctrl.angle.start_delay_tick);
 | 
				
			||||||
 | 
					WriteOutputArray(var, 2, 1);
 | 
				
			||||||
 | 
					var = phase_A.ctrl.angle.start_delay_tick;
 | 
				
			||||||
 | 
					WriteOutputArray(var, 2, 2);
 | 
				
			||||||
 | 
					var = TIMER->CNT;
 | 
				
			||||||
 | 
					WriteOutputArray(var, 2, 3);
 | 
				
			||||||
 | 
					// USER APP OUTPUT END
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										27
									
								
								app_wrapper/app_wrapper.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								app_wrapper/app_wrapper.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,27 @@
 | 
				
			|||||||
 | 
					#include "mcu_wrapper_conf.h"
 | 
				
			||||||
 | 
					#include "app_wrapper.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					  * @brief Функция для симуляции шага приложения МК
 | 
				
			||||||
 | 
					  * @details Используется в случае симуляции без отдельного потока для main().
 | 
				
			||||||
 | 
					  */
 | 
				
			||||||
 | 
					void app_step(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					// USER APP STEP START
 | 
				
			||||||
 | 
					// Код приложения МК для вызова в шаге симуляции
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Вызов разных функций на шаге симуляции в случае, 
 | 
				
			||||||
 | 
					// если не используется отдельный поток для main().
 | 
				
			||||||
 | 
					//upp_main();
 | 
				
			||||||
 | 
					// USER APP STEP END
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DUMMY START
 | 
				
			||||||
 | 
					// Заглушки для различных функций и переменных
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk) {}
 | 
				
			||||||
 | 
					void SystemClock_Config(void) {}
 | 
				
			||||||
 | 
					void Error_Handler(void) {}
 | 
				
			||||||
 | 
					// DUMMY END
 | 
				
			||||||
							
								
								
									
										12
									
								
								app_wrapper/app_wrapper.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								app_wrapper/app_wrapper.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					#ifndef _APP_WRAPPER_H_
 | 
				
			||||||
 | 
					#define _APP_WRAPPER_H_
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "app_includes.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void app_step(void);
 | 
				
			||||||
 | 
					void app_init(void);
 | 
				
			||||||
 | 
					void app_deinit(void);
 | 
				
			||||||
 | 
					void app_readInputs(const real_T* u);
 | 
				
			||||||
 | 
					void app_writeOutputBuffer(real_T* xD);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif //_APP_WRAPPER_H_
 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										734
									
								
								mexing.asv
									
									
									
									
									
								
							
							
						
						
									
										734
									
								
								mexing.asv
									
									
									
									
									
								
							@ -1,734 +0,0 @@
 | 
				
			|||||||
% Компилирует S-function
 | 
					 | 
				
			||||||
function mexing(compile_mode)
 | 
					 | 
				
			||||||
    global Ts
 | 
					 | 
				
			||||||
    Ts = 0.00001;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    if compile_mode == 1
 | 
					 | 
				
			||||||
        delete("*.mexw64")
 | 
					 | 
				
			||||||
        delete("*.mexw64.pdb")
 | 
					 | 
				
			||||||
        delete(".\MCU_Wrapper\Outputs\*.*");
 | 
					 | 
				
			||||||
        set_param(gcb, 'consoleOutput', '');    
 | 
					 | 
				
			||||||
        % Дефайны
 | 
					 | 
				
			||||||
        definesWrapperArg = buildWrapperDefinesString();
 | 
					 | 
				
			||||||
        definesUserArg = parseDefinesMaskText();
 | 
					 | 
				
			||||||
        definesConfigArg = buildConfigDefinesString();
 | 
					 | 
				
			||||||
        definesAllArg = [definesUserArg + " " + definesWrapperArg  + " " + definesConfigArg];    
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
        %режимы компиляции
 | 
					 | 
				
			||||||
        if read_checkbox('enableDebug')
 | 
					 | 
				
			||||||
            modeArg = "debug";
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            modeArg = "release";
 | 
					 | 
				
			||||||
        end    
 | 
					 | 
				
			||||||
        if read_checkbox('fullOutput') || read_checkbox('extConsol') 
 | 
					 | 
				
			||||||
            echoArg = 'echo_enable';
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            echoArg = 'echo_disable';    
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        [includesArg, codeArg] = make_mex_arguments('incTable', 'srcTable');
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        % Вызов батника с двумя параметрами: includes и code
 | 
					 | 
				
			||||||
        cmd = sprintf('.\\MCU_Wrapper\\run_mex.bat "%s" "%s" "%s" %s %s', includesArg, codeArg, definesAllArg, modeArg, echoArg);
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
        if read_checkbox('extConsol')
 | 
					 | 
				
			||||||
            cmdout = runBatAndShowOutput(cmd);
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            [status, cmdout]= system(cmd);
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        % Сохраним вывод в параметр маски с именем 'consoleOutput'
 | 
					 | 
				
			||||||
        set_param(gcb, 'consoleOutput', cmdout);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        beep
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
        blockPath = bdroot;
 | 
					 | 
				
			||||||
        config = read_periph_config();
 | 
					 | 
				
			||||||
        config = update_config_from_mask(blockPath, config);
 | 
					 | 
				
			||||||
        write_periph_config(config);
 | 
					 | 
				
			||||||
        update_mask_from_config(blockPath, config);
 | 
					 | 
				
			||||||
        % set_param(gcb, 'consoleOutput', 'Peripheral configuration file loaded. Re-open Block Parameters');
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
%% COMPILE PARAMS
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function [includesArg, codeArg] = make_mex_arguments(incTableName, srcTableame)
 | 
					 | 
				
			||||||
%MAKE_MEX_ARGUMENTS Формирует строки аргументов для вызова mex-компиляции через батник
 | 
					 | 
				
			||||||
%
 | 
					 | 
				
			||||||
% [includesArg, codeArg] = make_mex_arguments(includesCell, codeCell)
 | 
					 | 
				
			||||||
%
 | 
					 | 
				
			||||||
% Вход:
 | 
					 | 
				
			||||||
%   includesCell — ячейковый массив путей к директориям include
 | 
					 | 
				
			||||||
%   codeCell     — ячейковый массив исходных файлов
 | 
					 | 
				
			||||||
%
 | 
					 | 
				
			||||||
% Выход:
 | 
					 | 
				
			||||||
%   includesArg  — строка для передачи в батник, например: "-I"inc1" -I"inc2""
 | 
					 | 
				
			||||||
%   codeArg      — строка с исходниками, например: ""src1.c" "src2.cpp""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Здесь пример получения из маски текущего блока (замени по своему)
 | 
					 | 
				
			||||||
    blockHandle = gcbh;  % или замени на нужный блок
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    includesCell = parseCellString(get_param(blockHandle, incTableName));
 | 
					 | 
				
			||||||
    codeCell = parseCellString(get_param(blockHandle, srcTableame));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Оборачиваем пути в кавычки и добавляем -I
 | 
					 | 
				
			||||||
    includesStr = strjoin(cellfun(@(f) ['-I"' f '"'], includesCell, 'UniformOutput', false), ' ');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Оборачиваем имена файлов в кавычки
 | 
					 | 
				
			||||||
    codeStr = strjoin(cellfun(@(f) ['"' f '"'], codeCell, 'UniformOutput', false), ' ');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Удаляем символ переноса строки и пробел в конце, если вдруг попал
 | 
					 | 
				
			||||||
    codeStr = strtrim(codeStr);
 | 
					 | 
				
			||||||
    includesStr = strtrim(includesStr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Оборачиваем всю строку в кавычки, чтобы батник корректно понял
 | 
					 | 
				
			||||||
    % includesArg = ['"' includesStr '"'];
 | 
					 | 
				
			||||||
    % codeArg = ['"' codeStr '"'];
 | 
					 | 
				
			||||||
    includesArg = includesStr;
 | 
					 | 
				
			||||||
    codeArg = codeStr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function definesWrapperArg = buildWrapperDefinesString()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    definesWrapperArg = '';
 | 
					 | 
				
			||||||
    definesWrapperArg = addDefineByParam(definesWrapperArg, 'enableThreading', 0);
 | 
					 | 
				
			||||||
    definesWrapperArg = addDefineByParam(definesWrapperArg, 'enableDeinit', 0);
 | 
					 | 
				
			||||||
    definesWrapperArg = addDefineByParam(definesWrapperArg, 'threadCycles', 1);
 | 
					 | 
				
			||||||
    definesWrapperArg = addDefineByParam(definesWrapperArg, 'mcuClk', 1);
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function definesUserArg = parseDefinesMaskText()
 | 
					 | 
				
			||||||
    blockHandle = gcbh;
 | 
					 | 
				
			||||||
    % Получаем MaskValues и MaskNames
 | 
					 | 
				
			||||||
    maskValues = get_param(blockHandle, 'MaskValues');
 | 
					 | 
				
			||||||
    paramNames = get_param(blockHandle, 'MaskNames');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Индекс параметра userDefs
 | 
					 | 
				
			||||||
    idxUserDefs = find(strcmp(paramNames, 'userDefs'));
 | 
					 | 
				
			||||||
    definesText = maskValues{idxUserDefs}; % Текст с пользовательскими определениями
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Убираем буквальные символы \n и \r
 | 
					 | 
				
			||||||
    definesText = strrep(definesText, '\n', ' ');
 | 
					 | 
				
			||||||
    definesText = strrep(definesText, '\r', ' ');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Разбиваем по переносам строк
 | 
					 | 
				
			||||||
    lines = split(definesText, {'\n', '\r\n', '\r'});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    parts = strings(1,0); % пустой массив строк
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for k = 1:numel(lines)
 | 
					 | 
				
			||||||
        line = strtrim(lines{k});
 | 
					 | 
				
			||||||
        if isempty(line)
 | 
					 | 
				
			||||||
            continue;
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        % Разбиваем по пробелам, чтобы получить отдельные определения в строке
 | 
					 | 
				
			||||||
        tokens = split(line);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for t = 1:numel(tokens)
 | 
					 | 
				
			||||||
            token = strtrim(tokens{t});
 | 
					 | 
				
			||||||
            if isempty(token)
 | 
					 | 
				
			||||||
                continue;
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            eqIdx = strfind(token, '=');
 | 
					 | 
				
			||||||
            if isempty(eqIdx)
 | 
					 | 
				
			||||||
                % Просто ключ без значения
 | 
					 | 
				
			||||||
                parts(end+1) = sprintf('-D"%s"', token);
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
                key = strtrim(token(1:eqIdx(1)-1));
 | 
					 | 
				
			||||||
                val = strtrim(token(eqIdx(1)+1:end));
 | 
					 | 
				
			||||||
                parts(end+1) = sprintf('-D"%s__EQ__%s"', key, val);
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    definesUserArg = strjoin(parts, ' ');
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function definesWrapperArg = buildConfigDefinesString()
 | 
					 | 
				
			||||||
    blockHandle = gcbh;
 | 
					 | 
				
			||||||
    mask = Simulink.Mask.get(blockHandle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    tabName = 'configTabAll';  % Имя вкладки (Prompt)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    allControls = mask.getDialogControls();
 | 
					 | 
				
			||||||
    tabCtrl = find_container_by_name(allControls, tabName);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if isempty(tabCtrl)
 | 
					 | 
				
			||||||
        error('Вкладка с названием "%s" не найдена в маске', tabName);
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    collect_all_parameters
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    definesWrapperArg = '';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Получаем все контролы внутри вкладки
 | 
					 | 
				
			||||||
    children = tabCtrl.DialogControls;
 | 
					 | 
				
			||||||
    for i = 1:numel(children)
 | 
					 | 
				
			||||||
        ctrl = children(i);
 | 
					 | 
				
			||||||
        % Получаем имя параметра из контрола
 | 
					 | 
				
			||||||
        paramName = ctrl.Name;
 | 
					 | 
				
			||||||
            try
 | 
					 | 
				
			||||||
                % Получаем объект параметра по имени
 | 
					 | 
				
			||||||
                param = mask.getParameter(paramName);
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
                % Определяем тип параметра
 | 
					 | 
				
			||||||
                switch lower(param.Type)
 | 
					 | 
				
			||||||
                    case 'checkbox'
 | 
					 | 
				
			||||||
                        definesWrapperArg = addDefineByParam(definesWrapperArg, paramName, 0);
 | 
					 | 
				
			||||||
                    case 'edit'
 | 
					 | 
				
			||||||
                        definesWrapperArg = addDefineByParam(definesWrapperArg, paramName, 1);
 | 
					 | 
				
			||||||
                    otherwise
 | 
					 | 
				
			||||||
                        % Необрабатываемые типы
 | 
					 | 
				
			||||||
                end
 | 
					 | 
				
			||||||
            catch ME
 | 
					 | 
				
			||||||
                % warning('Не удалось получить параметр "%s": %s', paramName, ME.message);
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
%% PARSE FUNCTIONS
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function out = parseCellString(str)
 | 
					 | 
				
			||||||
    str = strtrim(str);
 | 
					 | 
				
			||||||
    if startsWith(str, '{') && endsWith(str, '}')
 | 
					 | 
				
			||||||
        str = str(2:end-1);
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    parts = split(str, ';');
 | 
					 | 
				
			||||||
    out = cell(numel(parts), 1);
 | 
					 | 
				
			||||||
    for i = 1:numel(parts)
 | 
					 | 
				
			||||||
        el = strtrim(parts{i});
 | 
					 | 
				
			||||||
        if startsWith(el, '''') && endsWith(el, '''')
 | 
					 | 
				
			||||||
            el = el(2:end-1);
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
        out{i} = el;
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if isempty(out) || (numel(out) == 1 && isempty(out{1}))
 | 
					 | 
				
			||||||
        out = {};
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function str = cellArrayToString(cellArray)
 | 
					 | 
				
			||||||
    quoted = cellfun(@(s) ['''' s ''''], cellArray, 'UniformOutput', false);
 | 
					 | 
				
			||||||
    str = ['{' strjoin(quoted, ';') '}'];
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function definesWrapperArg = addDefineByParam(definesWrapperArg, paramName, val_define)
 | 
					 | 
				
			||||||
    blockHandle = gcbh;
 | 
					 | 
				
			||||||
    mask = Simulink.Mask.get(blockHandle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Получаем MaskValues, MaskNames
 | 
					 | 
				
			||||||
    maskValues = get_param(blockHandle, 'MaskValues');
 | 
					 | 
				
			||||||
    paramNames = get_param(blockHandle, 'MaskNames');
 | 
					 | 
				
			||||||
    param = mask.getParameter(paramName); % для alias
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Найдём индекс нужного параметра
 | 
					 | 
				
			||||||
    idxParam = find(strcmp(paramNames, paramName), 1);
 | 
					 | 
				
			||||||
    if isempty(idxParam)
 | 
					 | 
				
			||||||
        error('Parameter "%s" not found in block mask parameters.', paramName);
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Берём alias из маски
 | 
					 | 
				
			||||||
    alias = param.Alias;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if val_define ~= 0
 | 
					 | 
				
			||||||
        % Значение параметра
 | 
					 | 
				
			||||||
        val = maskValues{idxParam};
 | 
					 | 
				
			||||||
        % Формируем define с кавычками и значением
 | 
					 | 
				
			||||||
        newDefine = ['-D"' alias '__EQ__' val '"'];
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
        if read_checkbox(paramName)
 | 
					 | 
				
			||||||
            % Формируем define с кавычками без значения
 | 
					 | 
				
			||||||
            newDefine = ['-D"' alias '"'];
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            newDefine = '';
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Добавляем новый define к существующему (string)
 | 
					 | 
				
			||||||
    if isempty(definesWrapperArg) || strlength(strtrim(definesWrapperArg)) == 0
 | 
					 | 
				
			||||||
        definesWrapperArg = newDefine;
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
        definesWrapperArg = definesWrapperArg + " " + newDefine;
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function checkbox_state = read_checkbox(checkboxName)
 | 
					 | 
				
			||||||
    maskValues = get_param(gcbh, 'MaskValues');
 | 
					 | 
				
			||||||
    paramNames = get_param(gcbh, 'MaskNames');
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    inxCheckBox = find(strcmp(paramNames, checkboxName));
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    checkbox_state_str = maskValues{inxCheckBox};
 | 
					 | 
				
			||||||
    if strcmpi(checkbox_state_str, 'on')
 | 
					 | 
				
			||||||
        checkbox_state = 1;
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
        checkbox_state = 0;
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
%% CONSOLE FUNCTIONS
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function cmdret = runBatAndShowOutput(cmd)
 | 
					 | 
				
			||||||
    import java.io.*;
 | 
					 | 
				
			||||||
    import java.lang.*;
 | 
					 | 
				
			||||||
    cmdEnglish = ['chcp 437 > nul && ' cmd];
 | 
					 | 
				
			||||||
    pb = java.lang.ProcessBuilder({'cmd.exe', '/c', cmdEnglish});
 | 
					 | 
				
			||||||
    pb.redirectErrorStream(true);
 | 
					 | 
				
			||||||
    process = pb.start();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    reader = BufferedReader(InputStreamReader(process.getInputStream()));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    cmdret = ""; % Здесь будем накапливать весь вывод
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    while true
 | 
					 | 
				
			||||||
        if reader.ready()
 | 
					 | 
				
			||||||
            line = char(reader.readLine());
 | 
					 | 
				
			||||||
            if isempty(line)
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
            cmdret = cmdret + string(line) + newline; % сохраняем вывод
 | 
					 | 
				
			||||||
            % Здесь выводим только новую строку
 | 
					 | 
				
			||||||
            safeLine = strrep(line, '''', ''''''); % Экранируем апострофы
 | 
					 | 
				
			||||||
            logWindow_append(safeLine);
 | 
					 | 
				
			||||||
            drawnow; % обновляем GUI
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            if ~process.isAlive()
 | 
					 | 
				
			||||||
                % дочитываем оставшиеся строки
 | 
					 | 
				
			||||||
                while reader.ready()
 | 
					 | 
				
			||||||
                    line = char(reader.readLine());
 | 
					 | 
				
			||||||
                    if isempty(line)
 | 
					 | 
				
			||||||
                        break;
 | 
					 | 
				
			||||||
                    end
 | 
					 | 
				
			||||||
                    cmdret = cmdret + string(line) + newline; % сохраняем вывод
 | 
					 | 
				
			||||||
                    safeLine = strrep(line, '''', '''''');
 | 
					 | 
				
			||||||
                    logWindow_append(safeLine);
 | 
					 | 
				
			||||||
                    drawnow;
 | 
					 | 
				
			||||||
                end
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
            pause(0.2);
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
    process.waitFor();
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function logWindow_append(line)
 | 
					 | 
				
			||||||
    persistent fig hEdit jScrollPane jTextArea
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if isempty(fig) || ~isvalid(fig)
 | 
					 | 
				
			||||||
        fig = figure('Name', 'Log Window', 'Position', [100 100 600 400]);
 | 
					 | 
				
			||||||
        hEdit = uicontrol('Style', 'edit', ...
 | 
					 | 
				
			||||||
            'Max', 2, 'Min', 0, ...
 | 
					 | 
				
			||||||
            'Enable', 'on', ...
 | 
					 | 
				
			||||||
            'FontName', 'Courier New', ...
 | 
					 | 
				
			||||||
            'Position', [10 10 580 380], ...
 | 
					 | 
				
			||||||
            'HorizontalAlignment', 'left', ...
 | 
					 | 
				
			||||||
            'BackgroundColor', 'white', ...
 | 
					 | 
				
			||||||
            'Tag', 'LogWindowFigure');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        jScrollPane = findjobj(hEdit);                  % JScrollPane
 | 
					 | 
				
			||||||
        jTextArea = jScrollPane.getViewport.getView;   % JTextArea внутри JScrollPane
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    oldText = get(hEdit, 'String');
 | 
					 | 
				
			||||||
    if ischar(oldText)
 | 
					 | 
				
			||||||
        oldText = {oldText};
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    set(hEdit, 'String', [oldText; {line}]);
 | 
					 | 
				
			||||||
    drawnow;
 | 
					 | 
				
			||||||
    % Автоскролл вниз:
 | 
					 | 
				
			||||||
    jTextArea.setCaretPosition(jTextArea.getDocument.getLength);
 | 
					 | 
				
			||||||
    drawnow;
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
%% READ CONFIGS
 | 
					 | 
				
			||||||
function config = read_periph_config()
 | 
					 | 
				
			||||||
    blockHandle = gcbh;
 | 
					 | 
				
			||||||
    mask = Simulink.Mask.get(blockHandle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pathparam = mask.getParameter('periphPath');
 | 
					 | 
				
			||||||
    config_path = pathparam.Value;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    jsonText = fileread(config_path);
 | 
					 | 
				
			||||||
    config = jsondecode(jsonText);
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function write_periph_config(config)
 | 
					 | 
				
			||||||
    blockHandle = gcbh;
 | 
					 | 
				
			||||||
    mask = Simulink.Mask.get(blockHandle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pathparam = mask.getParameter('periphPath');
 | 
					 | 
				
			||||||
    config_path = pathparam.Value;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    jsonText = jsonencode(config, 'PrettyPrint', true);
 | 
					 | 
				
			||||||
    fid = fopen(config_path, 'w');
 | 
					 | 
				
			||||||
    if fid == -1
 | 
					 | 
				
			||||||
        error('Не удалось открыть файл periph_config.json для записи.');
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
    fwrite(fid, jsonText, 'char');
 | 
					 | 
				
			||||||
    fclose(fid);
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
%% CONFIG MASK TOOLS
 | 
					 | 
				
			||||||
function update_mask_from_config(blockPath, config)
 | 
					 | 
				
			||||||
    blockPath = [blockPath '/MCU'];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Проверяем, была ли маска открыта
 | 
					 | 
				
			||||||
    wasOpen = isMaskDialogOpen(blockPath);
 | 
					 | 
				
			||||||
    close_system(blockPath, 0);
 | 
					 | 
				
			||||||
    mask = Simulink.Mask.get(blockPath);
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    tableNames = {'incTable', 'srcTable'};
 | 
					 | 
				
			||||||
    columns_backup = clear_tables(blockPath, tableNames);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    containerName = 'configTabAll';
 | 
					 | 
				
			||||||
    clear_all_from_container(mask, containerName);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Ищем контейнер, в который будем добавлять вкладки
 | 
					 | 
				
			||||||
    allControls = mask.getDialogControls();
 | 
					 | 
				
			||||||
    container = find_container_by_name(allControls, containerName);
 | 
					 | 
				
			||||||
    if isempty(container)
 | 
					 | 
				
			||||||
        error('Контейнер "%s" не найден в маске.', containerName);
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Проходим по каждому модулю (ADC, TIM...)
 | 
					 | 
				
			||||||
    periphs = fieldnames(config);
 | 
					 | 
				
			||||||
    for i = 1:numel(periphs)
 | 
					 | 
				
			||||||
        periph = periphs{i};
 | 
					 | 
				
			||||||
        defines = config.(periph).Defines;
 | 
					 | 
				
			||||||
        defNames = fieldnames(defines);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        % Создаём вкладку для модуля
 | 
					 | 
				
			||||||
        tabCtrl = container.addDialogControl('tab', periph);
 | 
					 | 
				
			||||||
        tabCtrl.Prompt = [periph ' Config'];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for j = 1:numel(defNames)
 | 
					 | 
				
			||||||
            defPrompt = defNames{j};
 | 
					 | 
				
			||||||
            def = defines.(defPrompt);
 | 
					 | 
				
			||||||
            prompt = def.Prompt;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            % Только checkbox и edit
 | 
					 | 
				
			||||||
            switch lower(def.Type)
 | 
					 | 
				
			||||||
                case 'checkbox'
 | 
					 | 
				
			||||||
                    paramType = 'checkbox';
 | 
					 | 
				
			||||||
                case 'edit'
 | 
					 | 
				
			||||||
                    paramType = 'edit';
 | 
					 | 
				
			||||||
                otherwise
 | 
					 | 
				
			||||||
                    continue;
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            paramName = matlab.lang.makeValidName(defPrompt);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            % Преобразуем значение по типу
 | 
					 | 
				
			||||||
            val = def.Default;
 | 
					 | 
				
			||||||
            if islogical(val)
 | 
					 | 
				
			||||||
                if val
 | 
					 | 
				
			||||||
                    valStr = 'on';
 | 
					 | 
				
			||||||
                else
 | 
					 | 
				
			||||||
                    valStr = 'off';
 | 
					 | 
				
			||||||
                end
 | 
					 | 
				
			||||||
            elseif isnumeric(val)
 | 
					 | 
				
			||||||
                valStr = num2str(val);
 | 
					 | 
				
			||||||
            elseif ischar(val)
 | 
					 | 
				
			||||||
                valStr = val;
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
                error('Unsupported default value type for %s.%s', periph, defPrompt);
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            % Добавляем параметр в соответствующую вкладку
 | 
					 | 
				
			||||||
            param = mask.addParameter( ...
 | 
					 | 
				
			||||||
                'Type', paramType, ...
 | 
					 | 
				
			||||||
                'Prompt', prompt, ...
 | 
					 | 
				
			||||||
                'Name', paramName, ...
 | 
					 | 
				
			||||||
                'Value', valStr, ...
 | 
					 | 
				
			||||||
                'Container', periph ...
 | 
					 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            param.Alias = def.Def;
 | 
					 | 
				
			||||||
            if def.NewRow
 | 
					 | 
				
			||||||
                row_param = 'new';
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
                row_param = 'current';
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
            param.DialogControl.Row = row_param;
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Восстанавливаем таблицы
 | 
					 | 
				
			||||||
    restore_tables(blockPath, tableNames, columns_backup);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Повторно открываем маску, если она была открыта
 | 
					 | 
				
			||||||
    if wasOpen
 | 
					 | 
				
			||||||
        open_system(blockPath, 'mask');
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function config = update_config_from_mask(blockPath, config)
 | 
					 | 
				
			||||||
    blockPath = [blockPath '/MCU'];
 | 
					 | 
				
			||||||
    mask = Simulink.Mask.get(blockPath);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    periphs = fieldnames(config);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for i = 1:numel(periphs)
 | 
					 | 
				
			||||||
        periph = periphs{i};
 | 
					 | 
				
			||||||
        defines = config.(periph).Defines;
 | 
					 | 
				
			||||||
        defNames = fieldnames(defines);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for j = 1:numel(defNames)
 | 
					 | 
				
			||||||
            defPrompt = defNames{j};
 | 
					 | 
				
			||||||
            paramName = matlab.lang.makeValidName(defPrompt);
 | 
					 | 
				
			||||||
            param = mask.getParameter(paramName);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            % Получаем значение из маски и сохраняем в конфиг
 | 
					 | 
				
			||||||
            valStr = param.Value;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            % Преобразуем строку в соответствующий тип
 | 
					 | 
				
			||||||
            if strcmpi(defines.(defPrompt).Type, 'checkbox')
 | 
					 | 
				
			||||||
                config.(periph).Defines.(defPrompt).Default = strcmpi(valStr, 'on');
 | 
					 | 
				
			||||||
            elseif strcmpi(defines.(defPrompt).Type, 'edit')
 | 
					 | 
				
			||||||
                valNum = str2double(valStr);
 | 
					 | 
				
			||||||
                if isnan(valNum)
 | 
					 | 
				
			||||||
                    config.(periph).Defines.(defPrompt).Default = valStr;
 | 
					 | 
				
			||||||
                else
 | 
					 | 
				
			||||||
                    config.(periph).Defines.(defPrompt).Default = valNum;
 | 
					 | 
				
			||||||
                end
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function clear_all_from_container(mask, containerName)
 | 
					 | 
				
			||||||
    allControls = mask.getDialogControls();
 | 
					 | 
				
			||||||
    container = find_container_by_name(allControls, containerName);
 | 
					 | 
				
			||||||
    if isempty(container)
 | 
					 | 
				
			||||||
        warning('Контейнер "%s" не найден.', containerName);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Рекурсивно собрать все параметры (не вкладки)
 | 
					 | 
				
			||||||
    paramsToDelete = collect_all_parameters(container);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Удаляем все параметры
 | 
					 | 
				
			||||||
    for i = 1:numel(paramsToDelete)
 | 
					 | 
				
			||||||
        try
 | 
					 | 
				
			||||||
            mask.removeParameter(paramsToDelete{i});
 | 
					 | 
				
			||||||
        catch
 | 
					 | 
				
			||||||
            warning('Не удалось удалить параметр %s', paramsToDelete{i});
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Рекурсивно удалить все вкладки внутри контейнера
 | 
					 | 
				
			||||||
    delete_all_tabs(mask, container);
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function params = collect_all_parameters(container)
 | 
					 | 
				
			||||||
    params = {};
 | 
					 | 
				
			||||||
    children = container.DialogControls;
 | 
					 | 
				
			||||||
    for i = 1:numel(children)
 | 
					 | 
				
			||||||
        ctrl = children(i);
 | 
					 | 
				
			||||||
        if isa(ctrl, 'Simulink.dialog.Tab')
 | 
					 | 
				
			||||||
            % Если вкладка — рекурсивно собираем параметры внутри неё
 | 
					 | 
				
			||||||
            params = [params, collect_all_parameters(ctrl)];
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            % Иначе это параметр — добавляем имя
 | 
					 | 
				
			||||||
            params{end+1} = ctrl.Name; %#ok<AGROW>
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function delete_all_tabs(mask, container)
 | 
					 | 
				
			||||||
    children = container.DialogControls;
 | 
					 | 
				
			||||||
    % Идём в обратном порядке, чтобы безопасно удалять
 | 
					 | 
				
			||||||
    for i = numel(children):-1:1
 | 
					 | 
				
			||||||
        ctrl = children(i);
 | 
					 | 
				
			||||||
        if isa(ctrl, 'Simulink.dialog.Tab')
 | 
					 | 
				
			||||||
            % Сначала рекурсивно удаляем вкладки внутри текущей вкладки
 | 
					 | 
				
			||||||
            delete_all_tabs(mask, ctrl);
 | 
					 | 
				
			||||||
            try
 | 
					 | 
				
			||||||
                container.removeDialogControl(ctrl.Name);
 | 
					 | 
				
			||||||
            catch ME
 | 
					 | 
				
			||||||
                warning('Не удалось удалить вкладку %s: %s', ctrl.Name, ME.message);
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function isOpen = isMaskDialogOpen(blockPath)
 | 
					 | 
				
			||||||
    isOpen = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    try
 | 
					 | 
				
			||||||
        % Получаем имя блока
 | 
					 | 
				
			||||||
        blockName = get_param(blockPath, 'Name');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        % Получаем список окон MATLAB GUI
 | 
					 | 
				
			||||||
        jWindows = java.awt.Window.getWindows();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for i = 1:numel(jWindows)
 | 
					 | 
				
			||||||
            win = jWindows(i);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            % Проверка, что окно видимое и активно
 | 
					 | 
				
			||||||
            if win.isShowing()
 | 
					 | 
				
			||||||
                try
 | 
					 | 
				
			||||||
                    title = char(win.getTitle());
 | 
					 | 
				
			||||||
                    % Проверка по ключевому слову, соответствующему заголовку маски
 | 
					 | 
				
			||||||
                    if contains(title, ['Mask Editor: ' blockName]) || ...
 | 
					 | 
				
			||||||
                       contains(title, ['Mask: ' blockName]) || ...
 | 
					 | 
				
			||||||
                       contains(title, blockName)
 | 
					 | 
				
			||||||
                        isOpen = true;
 | 
					 | 
				
			||||||
                        return;
 | 
					 | 
				
			||||||
                    end
 | 
					 | 
				
			||||||
                catch
 | 
					 | 
				
			||||||
                    % Окно не имеет заголовка — пропускаем
 | 
					 | 
				
			||||||
                end
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    catch
 | 
					 | 
				
			||||||
        isOpen = false;
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function column_titles = clear_tables(block, table_names)
 | 
					 | 
				
			||||||
    % Очищает столбцы в каждой таблице из массива имен table_names
 | 
					 | 
				
			||||||
    % Возвращает cell-массив с названиями первых столбцов каждой таблицы
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    % Получить объект маски блока
 | 
					 | 
				
			||||||
    maskObj = Simulink.Mask.get(block);
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    % Инициализировать cell-массив для хранения названий столбцов
 | 
					 | 
				
			||||||
    column_titles = cell(size(table_names));
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    for k = 1:numel(table_names)
 | 
					 | 
				
			||||||
        table_name = table_names{k};
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        % Получить объект управления таблицей
 | 
					 | 
				
			||||||
        tableControl = maskObj.getDialogControl(table_name);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        % Получить количество столбцов
 | 
					 | 
				
			||||||
        nCols = tableControl.getNumberOfColumns;
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        if nCols > 0
 | 
					 | 
				
			||||||
            % Получить первый столбец (который будем удалять)
 | 
					 | 
				
			||||||
            column = tableControl.getColumn(1);
 | 
					 | 
				
			||||||
            column_titles{k} = column.Name;
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            % Удаляем все столбцы
 | 
					 | 
				
			||||||
            % Важно: при удалении столбцов индексы меняются, 
 | 
					 | 
				
			||||||
            % поэтому удаляем всегда первый столбец nCols раз
 | 
					 | 
				
			||||||
            for i = 1:nCols
 | 
					 | 
				
			||||||
                tableControl.removeColumn(1);
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            % Если столбцов нет, возвращаем пустую строку
 | 
					 | 
				
			||||||
            column_titles{k} = '';
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function restore_tables(block, table_names, column_titles)
 | 
					 | 
				
			||||||
    % Восстанавливает первый столбец в каждой таблице из массива имен
 | 
					 | 
				
			||||||
    % Использует массив column_titles для установки имени столбца
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    % Получить объект маски блока
 | 
					 | 
				
			||||||
    maskObj = Simulink.Mask.get(block);
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    for k = 1:numel(table_names)
 | 
					 | 
				
			||||||
        table_name = table_names{k};
 | 
					 | 
				
			||||||
        title = column_titles{k};
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        % Получить объект управления таблицей
 | 
					 | 
				
			||||||
        tableControl = maskObj.getDialogControl(table_name);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        % Добавить новый столбец
 | 
					 | 
				
			||||||
        column = tableControl.addColumn(Name='title', Type='edit');
 | 
					 | 
				
			||||||
        column.Name = title;
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function tab = find_tab_by_name(controls, targetName)
 | 
					 | 
				
			||||||
    tab = [];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for i = 1:numel(controls)
 | 
					 | 
				
			||||||
        ctrl = controls(i);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        % Проверяем, вкладка ли это и совпадает ли имя
 | 
					 | 
				
			||||||
        if isa(ctrl, 'Simulink.dialog.Tab') && strcmp(ctrl.Name, targetName)
 | 
					 | 
				
			||||||
            tab = ctrl;
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        % Если это контейнер — обходим его детей
 | 
					 | 
				
			||||||
        children = get_children(ctrl);
 | 
					 | 
				
			||||||
        if ~isempty(children)
 | 
					 | 
				
			||||||
            tab = find_tab_by_name(children, targetName);
 | 
					 | 
				
			||||||
            if ~isempty(tab)
 | 
					 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function container = find_container_by_name(controls, targetName)
 | 
					 | 
				
			||||||
    container = [];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for i = 1:numel(controls)
 | 
					 | 
				
			||||||
        ctrl = controls(i);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        % Проверяем, контейнер ли это и совпадает ли имя
 | 
					 | 
				
			||||||
        if isa(ctrl, 'Simulink.dialog.Container') && strcmp(ctrl.Name, targetName)
 | 
					 | 
				
			||||||
            container = ctrl;
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        % Если это вложенный контрол — обходим его детей
 | 
					 | 
				
			||||||
        children = get_children(ctrl);
 | 
					 | 
				
			||||||
        if ~isempty(children)
 | 
					 | 
				
			||||||
            container = find_container_by_name(children, targetName);
 | 
					 | 
				
			||||||
            if ~isempty(container)
 | 
					 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function children = get_children(ctrl)
 | 
					 | 
				
			||||||
    if isprop(ctrl, 'DialogControls')
 | 
					 | 
				
			||||||
        children = ctrl.DialogControls;
 | 
					 | 
				
			||||||
    elseif isprop(ctrl, 'Controls')
 | 
					 | 
				
			||||||
        children = ctrl.Controls;
 | 
					 | 
				
			||||||
    elseif isprop(ctrl, 'Children')
 | 
					 | 
				
			||||||
        children = ctrl.Children;
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
        children = [];
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
							
								
								
									
										738
									
								
								mexing.m
									
									
									
									
									
								
							
							
						
						
									
										738
									
								
								mexing.m
									
									
									
									
									
								
							@ -1,738 +0,0 @@
 | 
				
			|||||||
% Компилирует S-function
 | 
					 | 
				
			||||||
function mexing(compile_mode)
 | 
					 | 
				
			||||||
    global Ts
 | 
					 | 
				
			||||||
    Ts = 0.00001;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    if compile_mode == 1
 | 
					 | 
				
			||||||
        delete("*.mexw64")
 | 
					 | 
				
			||||||
        delete("*.mexw64.pdb")
 | 
					 | 
				
			||||||
        delete(".\MCU_Wrapper\Outputs\*.*");
 | 
					 | 
				
			||||||
        set_param(gcb, 'consoleOutput', '');    
 | 
					 | 
				
			||||||
        % Дефайны
 | 
					 | 
				
			||||||
        definesWrapperArg = buildWrapperDefinesString();
 | 
					 | 
				
			||||||
        definesUserArg = parseDefinesMaskText();
 | 
					 | 
				
			||||||
        definesConfigArg = buildConfigDefinesString();
 | 
					 | 
				
			||||||
        definesAllArg = [definesUserArg + " " + definesWrapperArg  + " " + definesConfigArg];    
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
        %режимы компиляции
 | 
					 | 
				
			||||||
        if read_checkbox('enableDebug')
 | 
					 | 
				
			||||||
            modeArg = "debug";
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            modeArg = "release";
 | 
					 | 
				
			||||||
        end    
 | 
					 | 
				
			||||||
        if read_checkbox('fullOutput') || read_checkbox('extConsol') 
 | 
					 | 
				
			||||||
            echoArg = 'echo_enable';
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            echoArg = 'echo_disable';    
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        [includesArg, codeArg] = make_mex_arguments('incTable', 'srcTable');
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        % Вызов батника с двумя параметрами: includes и code
 | 
					 | 
				
			||||||
        cmd = sprintf('.\\MCU_Wrapper\\run_mex.bat "%s" "%s" "%s" %s %s', includesArg, codeArg, definesAllArg, modeArg, echoArg);
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
        if read_checkbox('extConsol')
 | 
					 | 
				
			||||||
            cmdout = runBatAndShowOutput(cmd);
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            [status, cmdout]= system(cmd);
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        % Сохраним вывод в параметр маски с именем 'consoleOutput'
 | 
					 | 
				
			||||||
        set_param(gcb, 'consoleOutput', cmdout);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        beep
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
        blockPath = bdroot;
 | 
					 | 
				
			||||||
        config = read_periph_config();
 | 
					 | 
				
			||||||
        config = update_config_from_mask(blockPath, config);
 | 
					 | 
				
			||||||
        write_periph_config(config);
 | 
					 | 
				
			||||||
        update_mask_from_config(blockPath, config);
 | 
					 | 
				
			||||||
        % set_param(gcb, 'consoleOutput', 'Peripheral configuration file loaded. Re-open Block Parameters');
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
%% COMPILE PARAMS
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function [includesArg, codeArg] = make_mex_arguments(incTableName, srcTableame)
 | 
					 | 
				
			||||||
%MAKE_MEX_ARGUMENTS Формирует строки аргументов для вызова mex-компиляции через батник
 | 
					 | 
				
			||||||
%
 | 
					 | 
				
			||||||
% [includesArg, codeArg] = make_mex_arguments(includesCell, codeCell)
 | 
					 | 
				
			||||||
%
 | 
					 | 
				
			||||||
% Вход:
 | 
					 | 
				
			||||||
%   includesCell — ячейковый массив путей к директориям include
 | 
					 | 
				
			||||||
%   codeCell     — ячейковый массив исходных файлов
 | 
					 | 
				
			||||||
%
 | 
					 | 
				
			||||||
% Выход:
 | 
					 | 
				
			||||||
%   includesArg  — строка для передачи в батник, например: "-I"inc1" -I"inc2""
 | 
					 | 
				
			||||||
%   codeArg      — строка с исходниками, например: ""src1.c" "src2.cpp""
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Здесь пример получения из маски текущего блока (замени по своему)
 | 
					 | 
				
			||||||
    blockHandle = gcbh;  % или замени на нужный блок
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    includesCell = parseCellString(get_param(blockHandle, incTableName));
 | 
					 | 
				
			||||||
    codeCell = parseCellString(get_param(blockHandle, srcTableame));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Оборачиваем пути в кавычки и добавляем -I
 | 
					 | 
				
			||||||
    includesStr = strjoin(cellfun(@(f) ['-I"' f '"'], includesCell, 'UniformOutput', false), ' ');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Оборачиваем имена файлов в кавычки
 | 
					 | 
				
			||||||
    codeStr = strjoin(cellfun(@(f) ['"' f '"'], codeCell, 'UniformOutput', false), ' ');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Удаляем символ переноса строки и пробел в конце, если вдруг попал
 | 
					 | 
				
			||||||
    codeStr = strtrim(codeStr);
 | 
					 | 
				
			||||||
    includesStr = strtrim(includesStr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Оборачиваем всю строку в кавычки, чтобы батник корректно понял
 | 
					 | 
				
			||||||
    % includesArg = ['"' includesStr '"'];
 | 
					 | 
				
			||||||
    % codeArg = ['"' codeStr '"'];
 | 
					 | 
				
			||||||
    includesArg = includesStr;
 | 
					 | 
				
			||||||
    codeArg = codeStr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function definesWrapperArg = buildWrapperDefinesString()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    definesWrapperArg = '';
 | 
					 | 
				
			||||||
    definesWrapperArg = addDefineByParam(definesWrapperArg, 'enableThreading', 0);
 | 
					 | 
				
			||||||
    definesWrapperArg = addDefineByParam(definesWrapperArg, 'enableDeinit', 0);
 | 
					 | 
				
			||||||
    definesWrapperArg = addDefineByParam(definesWrapperArg, 'threadCycles', 1);
 | 
					 | 
				
			||||||
    definesWrapperArg = addDefineByParam(definesWrapperArg, 'mcuClk', 1);
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function definesUserArg = parseDefinesMaskText()
 | 
					 | 
				
			||||||
    blockHandle = gcbh;
 | 
					 | 
				
			||||||
    % Получаем MaskValues и MaskNames
 | 
					 | 
				
			||||||
    maskValues = get_param(blockHandle, 'MaskValues');
 | 
					 | 
				
			||||||
    paramNames = get_param(blockHandle, 'MaskNames');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Индекс параметра userDefs
 | 
					 | 
				
			||||||
    idxUserDefs = find(strcmp(paramNames, 'userDefs'));
 | 
					 | 
				
			||||||
    definesText = maskValues{idxUserDefs}; % Текст с пользовательскими определениями
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Убираем буквальные символы \n и \r
 | 
					 | 
				
			||||||
    definesText = strrep(definesText, '\n', ' ');
 | 
					 | 
				
			||||||
    definesText = strrep(definesText, '\r', ' ');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Разбиваем по переносам строк
 | 
					 | 
				
			||||||
    lines = split(definesText, {'\n', '\r\n', '\r'});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    parts = strings(1,0); % пустой массив строк
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for k = 1:numel(lines)
 | 
					 | 
				
			||||||
        line = strtrim(lines{k});
 | 
					 | 
				
			||||||
        if isempty(line)
 | 
					 | 
				
			||||||
            continue;
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        % Разбиваем по пробелам, чтобы получить отдельные определения в строке
 | 
					 | 
				
			||||||
        tokens = split(line);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for t = 1:numel(tokens)
 | 
					 | 
				
			||||||
            token = strtrim(tokens{t});
 | 
					 | 
				
			||||||
            if isempty(token)
 | 
					 | 
				
			||||||
                continue;
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            eqIdx = strfind(token, '=');
 | 
					 | 
				
			||||||
            if isempty(eqIdx)
 | 
					 | 
				
			||||||
                % Просто ключ без значения
 | 
					 | 
				
			||||||
                parts(end+1) = sprintf('-D"%s"', token);
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
                key = strtrim(token(1:eqIdx(1)-1));
 | 
					 | 
				
			||||||
                val = strtrim(token(eqIdx(1)+1:end));
 | 
					 | 
				
			||||||
                parts(end+1) = sprintf('-D"%s__EQ__%s"', key, val);
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    definesUserArg = strjoin(parts, ' ');
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function definesWrapperArg = buildConfigDefinesString()
 | 
					 | 
				
			||||||
    blockHandle = gcbh;
 | 
					 | 
				
			||||||
    mask = Simulink.Mask.get(blockHandle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    tabName = 'configTabAll';  % Имя вкладки (Prompt)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    allControls = mask.getDialogControls();
 | 
					 | 
				
			||||||
    tabCtrl = find_container_by_name(allControls, tabName);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if isempty(tabCtrl)
 | 
					 | 
				
			||||||
        error('Вкладка с названием "%s" не найдена в маске', tabName);
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    params = collect_all_parameters(tabCtrl);
 | 
					 | 
				
			||||||
    definesWrapperArg = '';
 | 
					 | 
				
			||||||
    for i = 1:numel(params)
 | 
					 | 
				
			||||||
        % Получаем имя параметра из контрола
 | 
					 | 
				
			||||||
        paramName = string(params(i));
 | 
					 | 
				
			||||||
        try
 | 
					 | 
				
			||||||
            % Получаем объект параметра по имени
 | 
					 | 
				
			||||||
            param = mask.getParameter(paramName);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            % Определяем тип параметра
 | 
					 | 
				
			||||||
            switch lower(param.Type)
 | 
					 | 
				
			||||||
                case 'checkbox'
 | 
					 | 
				
			||||||
                    definesWrapperArg = addDefineByParam(definesWrapperArg, paramName, 0);
 | 
					 | 
				
			||||||
                case 'edit'
 | 
					 | 
				
			||||||
                    definesWrapperArg = addDefineByParam(definesWrapperArg, paramName, 1);
 | 
					 | 
				
			||||||
                otherwise
 | 
					 | 
				
			||||||
                    % Необрабатываемые типы
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
        catch ME
 | 
					 | 
				
			||||||
            % warning('Не удалось получить параметр "%s": %s', paramName, ME.message);
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
%% PARSE FUNCTIONS
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function out = parseCellString(str)
 | 
					 | 
				
			||||||
    str = strtrim(str);
 | 
					 | 
				
			||||||
    if startsWith(str, '{') && endsWith(str, '}')
 | 
					 | 
				
			||||||
        str = str(2:end-1);
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    parts = split(str, ';');
 | 
					 | 
				
			||||||
    out = cell(numel(parts), 1);
 | 
					 | 
				
			||||||
    for i = 1:numel(parts)
 | 
					 | 
				
			||||||
        el = strtrim(parts{i});
 | 
					 | 
				
			||||||
        if startsWith(el, '''') && endsWith(el, '''')
 | 
					 | 
				
			||||||
            el = el(2:end-1);
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
        out{i} = el;
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if isempty(out) || (numel(out) == 1 && isempty(out{1}))
 | 
					 | 
				
			||||||
        out = {};
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function str = cellArrayToString(cellArray)
 | 
					 | 
				
			||||||
    quoted = cellfun(@(s) ['''' s ''''], cellArray, 'UniformOutput', false);
 | 
					 | 
				
			||||||
    str = ['{' strjoin(quoted, ';') '}'];
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function definesWrapperArg = addDefineByParam(definesWrapperArg, paramName, val_define)
 | 
					 | 
				
			||||||
    blockHandle = gcbh;
 | 
					 | 
				
			||||||
    mask = Simulink.Mask.get(blockHandle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Получаем MaskValues, MaskNames
 | 
					 | 
				
			||||||
    maskValues = get_param(blockHandle, 'MaskValues');
 | 
					 | 
				
			||||||
    paramNames = get_param(blockHandle, 'MaskNames');
 | 
					 | 
				
			||||||
    param = mask.getParameter(paramName); % для alias
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Найдём индекс нужного параметра
 | 
					 | 
				
			||||||
    idxParam = find(strcmp(paramNames, paramName), 1);
 | 
					 | 
				
			||||||
    if isempty(idxParam)
 | 
					 | 
				
			||||||
        error('Parameter "%s" not found in block mask parameters.', paramName);
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Берём alias из маски
 | 
					 | 
				
			||||||
    alias = param.Alias;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if val_define ~= 0
 | 
					 | 
				
			||||||
        % Значение параметра
 | 
					 | 
				
			||||||
        val = maskValues{idxParam};
 | 
					 | 
				
			||||||
        % Формируем define с кавычками и значением
 | 
					 | 
				
			||||||
        newDefine = ['-D"' alias '__EQ__' val '"'];
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
        if read_checkbox(paramName)
 | 
					 | 
				
			||||||
            % Формируем define с кавычками без значения
 | 
					 | 
				
			||||||
            newDefine = ['-D"' alias '"'];
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            newDefine = '';
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Добавляем новый define к существующему (string)
 | 
					 | 
				
			||||||
    if isempty(definesWrapperArg) || strlength(strtrim(definesWrapperArg)) == 0
 | 
					 | 
				
			||||||
        definesWrapperArg = newDefine;
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
        definesWrapperArg = definesWrapperArg + " " + newDefine;
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function checkbox_state = read_checkbox(checkboxName)
 | 
					 | 
				
			||||||
    maskValues = get_param(gcbh, 'MaskValues');
 | 
					 | 
				
			||||||
    paramNames = get_param(gcbh, 'MaskNames');
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    inxCheckBox = find(strcmp(paramNames, checkboxName));
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    checkbox_state_str = maskValues{inxCheckBox};
 | 
					 | 
				
			||||||
    if strcmpi(checkbox_state_str, 'on')
 | 
					 | 
				
			||||||
        checkbox_state = 1;
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
        checkbox_state = 0;
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
%% CONSOLE FUNCTIONS
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function cmdret = runBatAndShowOutput(cmd)
 | 
					 | 
				
			||||||
    import java.io.*;
 | 
					 | 
				
			||||||
    import java.lang.*;
 | 
					 | 
				
			||||||
    cmdEnglish = ['chcp 437 > nul && ' cmd];
 | 
					 | 
				
			||||||
    pb = java.lang.ProcessBuilder({'cmd.exe', '/c', cmdEnglish});
 | 
					 | 
				
			||||||
    pb.redirectErrorStream(true);
 | 
					 | 
				
			||||||
    process = pb.start();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    reader = BufferedReader(InputStreamReader(process.getInputStream()));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    cmdret = ""; % Здесь будем накапливать весь вывод
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    while true
 | 
					 | 
				
			||||||
        if reader.ready()
 | 
					 | 
				
			||||||
            line = char(reader.readLine());
 | 
					 | 
				
			||||||
            if isempty(line)
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
            cmdret = cmdret + string(line) + newline; % сохраняем вывод
 | 
					 | 
				
			||||||
            % Здесь выводим только новую строку
 | 
					 | 
				
			||||||
            safeLine = strrep(line, '''', ''''''); % Экранируем апострофы
 | 
					 | 
				
			||||||
            logWindow_append(safeLine);
 | 
					 | 
				
			||||||
            drawnow; % обновляем GUI
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            if ~process.isAlive()
 | 
					 | 
				
			||||||
                % дочитываем оставшиеся строки
 | 
					 | 
				
			||||||
                while reader.ready()
 | 
					 | 
				
			||||||
                    line = char(reader.readLine());
 | 
					 | 
				
			||||||
                    if isempty(line)
 | 
					 | 
				
			||||||
                        break;
 | 
					 | 
				
			||||||
                    end
 | 
					 | 
				
			||||||
                    cmdret = cmdret + string(line) + newline; % сохраняем вывод
 | 
					 | 
				
			||||||
                    safeLine = strrep(line, '''', '''''');
 | 
					 | 
				
			||||||
                    logWindow_append(safeLine);
 | 
					 | 
				
			||||||
                    drawnow;
 | 
					 | 
				
			||||||
                end
 | 
					 | 
				
			||||||
                break;
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
            pause(0.2);
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
    process.waitFor();
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function logWindow_append(line)
 | 
					 | 
				
			||||||
    persistent fig hEdit jScrollPane jTextArea
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if isempty(fig) || ~isvalid(fig)
 | 
					 | 
				
			||||||
        fig = figure('Name', 'Log Window', 'Position', [100 100 600 400]);
 | 
					 | 
				
			||||||
        hEdit = uicontrol('Style', 'edit', ...
 | 
					 | 
				
			||||||
            'Max', 2, 'Min', 0, ...
 | 
					 | 
				
			||||||
            'Enable', 'on', ...
 | 
					 | 
				
			||||||
            'FontName', 'Courier New', ...
 | 
					 | 
				
			||||||
            'Position', [10 10 580 380], ...
 | 
					 | 
				
			||||||
            'HorizontalAlignment', 'left', ...
 | 
					 | 
				
			||||||
            'BackgroundColor', 'white', ...
 | 
					 | 
				
			||||||
            'Tag', 'LogWindowFigure');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        jScrollPane = findjobj(hEdit);                  % JScrollPane
 | 
					 | 
				
			||||||
        jTextArea = jScrollPane.getViewport.getView;   % JTextArea внутри JScrollPane
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    oldText = get(hEdit, 'String');
 | 
					 | 
				
			||||||
    if ischar(oldText)
 | 
					 | 
				
			||||||
        oldText = {oldText};
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    set(hEdit, 'String', [oldText; {line}]);
 | 
					 | 
				
			||||||
    drawnow;
 | 
					 | 
				
			||||||
    % Автоскролл вниз:
 | 
					 | 
				
			||||||
    jTextArea.setCaretPosition(jTextArea.getDocument.getLength);
 | 
					 | 
				
			||||||
    drawnow;
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
%% READ CONFIGS
 | 
					 | 
				
			||||||
function config = read_periph_config()
 | 
					 | 
				
			||||||
    blockHandle = gcbh;
 | 
					 | 
				
			||||||
    mask = Simulink.Mask.get(blockHandle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pathparam = mask.getParameter('periphPath');
 | 
					 | 
				
			||||||
    config_path = pathparam.Value;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    jsonText = fileread(config_path);
 | 
					 | 
				
			||||||
    config = jsondecode(jsonText);
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function write_periph_config(config)
 | 
					 | 
				
			||||||
    blockHandle = gcbh;
 | 
					 | 
				
			||||||
    mask = Simulink.Mask.get(blockHandle);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pathparam = mask.getParameter('periphPath');
 | 
					 | 
				
			||||||
    config_path = pathparam.Value;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    jsonText = jsonencode(config, 'PrettyPrint', true);
 | 
					 | 
				
			||||||
    fid = fopen(config_path, 'w');
 | 
					 | 
				
			||||||
    if fid == -1
 | 
					 | 
				
			||||||
        error('Не удалось открыть файл periph_config.json для записи.');
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
    fwrite(fid, jsonText, 'char');
 | 
					 | 
				
			||||||
    fclose(fid);
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
%% CONFIG MASK TOOLS
 | 
					 | 
				
			||||||
function update_mask_from_config(blockPath, config)
 | 
					 | 
				
			||||||
    blockPath = [blockPath '/MCU'];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Проверяем, была ли маска открыта
 | 
					 | 
				
			||||||
    wasOpen = isMaskDialogOpen(blockPath);
 | 
					 | 
				
			||||||
    close_system(blockPath, 0);
 | 
					 | 
				
			||||||
    mask = Simulink.Mask.get(blockPath);
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    tableNames = {'incTable', 'srcTable'};
 | 
					 | 
				
			||||||
    columns_backup = clear_tables(blockPath, tableNames);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    containerName = 'configTabAll';
 | 
					 | 
				
			||||||
    clear_all_from_container(mask, containerName);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Ищем контейнер, в который будем добавлять вкладки
 | 
					 | 
				
			||||||
    allControls = mask.getDialogControls();
 | 
					 | 
				
			||||||
    container = find_container_by_name(allControls, containerName);
 | 
					 | 
				
			||||||
    if isempty(container)
 | 
					 | 
				
			||||||
        error('Контейнер "%s" не найден в маске.', containerName);
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Проходим по каждому модулю (ADC, TIM...)
 | 
					 | 
				
			||||||
    periphs = fieldnames(config);
 | 
					 | 
				
			||||||
    for i = 1:numel(periphs)
 | 
					 | 
				
			||||||
        periph = periphs{i};
 | 
					 | 
				
			||||||
        defines = config.(periph).Defines;
 | 
					 | 
				
			||||||
        defNames = fieldnames(defines);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        % Создаём вкладку для модуля
 | 
					 | 
				
			||||||
        tabCtrl = container.addDialogControl('tab', periph);
 | 
					 | 
				
			||||||
        tabCtrl.Prompt = [periph ' Config'];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for j = 1:numel(defNames)
 | 
					 | 
				
			||||||
            defPrompt = defNames{j};
 | 
					 | 
				
			||||||
            def = defines.(defPrompt);
 | 
					 | 
				
			||||||
            prompt = def.Prompt;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            % Только checkbox и edit
 | 
					 | 
				
			||||||
            switch lower(def.Type)
 | 
					 | 
				
			||||||
                case 'checkbox'
 | 
					 | 
				
			||||||
                    paramType = 'checkbox';
 | 
					 | 
				
			||||||
                case 'edit'
 | 
					 | 
				
			||||||
                    paramType = 'edit';
 | 
					 | 
				
			||||||
                otherwise
 | 
					 | 
				
			||||||
                    continue;
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            paramName = matlab.lang.makeValidName(defPrompt);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            % Преобразуем значение по типу
 | 
					 | 
				
			||||||
            val = def.Default;
 | 
					 | 
				
			||||||
            if islogical(val)
 | 
					 | 
				
			||||||
                if val
 | 
					 | 
				
			||||||
                    valStr = 'on';
 | 
					 | 
				
			||||||
                else
 | 
					 | 
				
			||||||
                    valStr = 'off';
 | 
					 | 
				
			||||||
                end
 | 
					 | 
				
			||||||
            elseif isnumeric(val)
 | 
					 | 
				
			||||||
                valStr = num2str(val);
 | 
					 | 
				
			||||||
            elseif ischar(val)
 | 
					 | 
				
			||||||
                valStr = val;
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
                error('Unsupported default value type for %s.%s', periph, defPrompt);
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            % Добавляем параметр в соответствующую вкладку
 | 
					 | 
				
			||||||
            param = mask.addParameter( ...
 | 
					 | 
				
			||||||
                'Type', paramType, ...
 | 
					 | 
				
			||||||
                'Prompt', prompt, ...
 | 
					 | 
				
			||||||
                'Name', paramName, ...
 | 
					 | 
				
			||||||
                'Value', valStr, ...
 | 
					 | 
				
			||||||
                'Container', periph ...
 | 
					 | 
				
			||||||
            );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            param.Alias = def.Def;
 | 
					 | 
				
			||||||
            if def.NewRow
 | 
					 | 
				
			||||||
                row_param = 'new';
 | 
					 | 
				
			||||||
            else
 | 
					 | 
				
			||||||
                row_param = 'current';
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
            param.DialogControl.Row = row_param;
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Восстанавливаем таблицы
 | 
					 | 
				
			||||||
    restore_tables(blockPath, tableNames, columns_backup);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Повторно открываем маску, если она была открыта
 | 
					 | 
				
			||||||
    if wasOpen
 | 
					 | 
				
			||||||
        open_system(blockPath, 'mask');
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function config = update_config_from_mask(blockPath, config)
 | 
					 | 
				
			||||||
    blockPath = [blockPath '/MCU'];
 | 
					 | 
				
			||||||
    mask = Simulink.Mask.get(blockPath);
 | 
					 | 
				
			||||||
    maskParams = mask.Parameters;
 | 
					 | 
				
			||||||
    paramNames = arrayfun(@(p) p.Name, maskParams, 'UniformOutput', false);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    periphs = fieldnames(config);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for i = 1:numel(periphs)
 | 
					 | 
				
			||||||
        periph = periphs{i};
 | 
					 | 
				
			||||||
        defines = config.(periph).Defines;
 | 
					 | 
				
			||||||
        defNames = fieldnames(defines);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for j = 1:numel(defNames)
 | 
					 | 
				
			||||||
            defPrompt = defNames{j};
 | 
					 | 
				
			||||||
            paramName = matlab.lang.makeValidName(defPrompt);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            % Проверка, существует ли параметр с таким именем
 | 
					 | 
				
			||||||
            if ismember(paramName, paramNames)
 | 
					 | 
				
			||||||
                param = mask.getParameter(paramName);    
 | 
					 | 
				
			||||||
                % Получаем значение из маски и сохраняем в конфиг
 | 
					 | 
				
			||||||
                valStr = param.Value;
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
                % Проверяем, существует ли элемент defPrompt в структуре defines
 | 
					 | 
				
			||||||
                if isfield(defines, defPrompt)
 | 
					 | 
				
			||||||
                    % Преобразуем строку в соответствующий тип
 | 
					 | 
				
			||||||
                    if strcmpi(defines.(defPrompt).Type, 'checkbox')
 | 
					 | 
				
			||||||
                        config.(periph).Defines.(defPrompt).Default = strcmpi(valStr, 'on');
 | 
					 | 
				
			||||||
                    elseif strcmpi(defines.(defPrompt).Type, 'edit')
 | 
					 | 
				
			||||||
                        valNum = str2double(valStr);
 | 
					 | 
				
			||||||
                        if isnan(valNum)
 | 
					 | 
				
			||||||
                            config.(periph).Defines.(defPrompt).Default = valStr;
 | 
					 | 
				
			||||||
                        else
 | 
					 | 
				
			||||||
                            config.(periph).Defines.(defPrompt).Default = valNum;
 | 
					 | 
				
			||||||
                        end
 | 
					 | 
				
			||||||
                    end
 | 
					 | 
				
			||||||
                end
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function clear_all_from_container(mask, containerName)
 | 
					 | 
				
			||||||
    allControls = mask.getDialogControls();
 | 
					 | 
				
			||||||
    container = find_container_by_name(allControls, containerName);
 | 
					 | 
				
			||||||
    if isempty(container)
 | 
					 | 
				
			||||||
        warning('Контейнер "%s" не найден.', containerName);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Рекурсивно собрать все параметры (не вкладки)
 | 
					 | 
				
			||||||
    paramsToDelete = collect_all_parameters(container);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Удаляем все параметры
 | 
					 | 
				
			||||||
    for i = 1:numel(paramsToDelete)
 | 
					 | 
				
			||||||
        try
 | 
					 | 
				
			||||||
            mask.removeParameter(paramsToDelete{i});
 | 
					 | 
				
			||||||
        catch
 | 
					 | 
				
			||||||
            warning('Не удалось удалить параметр %s', paramsToDelete{i});
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    % Рекурсивно удалить все вкладки внутри контейнера
 | 
					 | 
				
			||||||
    delete_all_tabs(mask, container);
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function params = collect_all_parameters(container)
 | 
					 | 
				
			||||||
    params = {};
 | 
					 | 
				
			||||||
    children = container.DialogControls;
 | 
					 | 
				
			||||||
    for i = 1:numel(children)
 | 
					 | 
				
			||||||
        ctrl = children(i);
 | 
					 | 
				
			||||||
        if isa(ctrl, 'Simulink.dialog.Tab')
 | 
					 | 
				
			||||||
            % Если вкладка — рекурсивно собираем параметры внутри неё
 | 
					 | 
				
			||||||
            params = [params, collect_all_parameters(ctrl)];
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            % Иначе это параметр — добавляем имя
 | 
					 | 
				
			||||||
            params{end+1} = ctrl.Name; %#ok<AGROW>
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function delete_all_tabs(mask, container)
 | 
					 | 
				
			||||||
    children = container.DialogControls;
 | 
					 | 
				
			||||||
    % Идём в обратном порядке, чтобы безопасно удалять
 | 
					 | 
				
			||||||
    for i = numel(children):-1:1
 | 
					 | 
				
			||||||
        ctrl = children(i);
 | 
					 | 
				
			||||||
        if isa(ctrl, 'Simulink.dialog.Tab')
 | 
					 | 
				
			||||||
            % Сначала рекурсивно удаляем вкладки внутри текущей вкладки
 | 
					 | 
				
			||||||
            delete_all_tabs(mask, ctrl);
 | 
					 | 
				
			||||||
            try
 | 
					 | 
				
			||||||
                container.removeDialogControl(ctrl.Name);
 | 
					 | 
				
			||||||
            catch ME
 | 
					 | 
				
			||||||
                warning('Не удалось удалить вкладку %s: %s', ctrl.Name, ME.message);
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function isOpen = isMaskDialogOpen(blockPath)
 | 
					 | 
				
			||||||
    isOpen = false;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    try
 | 
					 | 
				
			||||||
        % Получаем имя блока
 | 
					 | 
				
			||||||
        blockName = get_param(blockPath, 'Name');
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        % Получаем список окон MATLAB GUI
 | 
					 | 
				
			||||||
        jWindows = java.awt.Window.getWindows();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        for i = 1:numel(jWindows)
 | 
					 | 
				
			||||||
            win = jWindows(i);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            % Проверка, что окно видимое и активно
 | 
					 | 
				
			||||||
            if win.isShowing()
 | 
					 | 
				
			||||||
                try
 | 
					 | 
				
			||||||
                    title = char(win.getTitle());
 | 
					 | 
				
			||||||
                    % Проверка по ключевому слову, соответствующему заголовку маски
 | 
					 | 
				
			||||||
                    if contains(title, ['Mask Editor: ' blockName]) || ...
 | 
					 | 
				
			||||||
                       contains(title, ['Mask: ' blockName]) || ...
 | 
					 | 
				
			||||||
                       contains(title, blockName)
 | 
					 | 
				
			||||||
                        isOpen = true;
 | 
					 | 
				
			||||||
                        return;
 | 
					 | 
				
			||||||
                    end
 | 
					 | 
				
			||||||
                catch
 | 
					 | 
				
			||||||
                    % Окно не имеет заголовка — пропускаем
 | 
					 | 
				
			||||||
                end
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    catch
 | 
					 | 
				
			||||||
        isOpen = false;
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function column_titles = clear_tables(block, table_names)
 | 
					 | 
				
			||||||
    % Очищает столбцы в каждой таблице из массива имен table_names
 | 
					 | 
				
			||||||
    % Возвращает cell-массив с названиями первых столбцов каждой таблицы
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    % Получить объект маски блока
 | 
					 | 
				
			||||||
    maskObj = Simulink.Mask.get(block);
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    % Инициализировать cell-массив для хранения названий столбцов
 | 
					 | 
				
			||||||
    column_titles = cell(size(table_names));
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    for k = 1:numel(table_names)
 | 
					 | 
				
			||||||
        table_name = table_names{k};
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        % Получить объект управления таблицей
 | 
					 | 
				
			||||||
        tableControl = maskObj.getDialogControl(table_name);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        % Получить количество столбцов
 | 
					 | 
				
			||||||
        nCols = tableControl.getNumberOfColumns;
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        if nCols > 0
 | 
					 | 
				
			||||||
            % Получить первый столбец (который будем удалять)
 | 
					 | 
				
			||||||
            column = tableControl.getColumn(1);
 | 
					 | 
				
			||||||
            column_titles{k} = column.Name;
 | 
					 | 
				
			||||||
            
 | 
					 | 
				
			||||||
            % Удаляем все столбцы
 | 
					 | 
				
			||||||
            % Важно: при удалении столбцов индексы меняются, 
 | 
					 | 
				
			||||||
            % поэтому удаляем всегда первый столбец nCols раз
 | 
					 | 
				
			||||||
            for i = 1:nCols
 | 
					 | 
				
			||||||
                tableControl.removeColumn(1);
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
        else
 | 
					 | 
				
			||||||
            % Если столбцов нет, возвращаем пустую строку
 | 
					 | 
				
			||||||
            column_titles{k} = '';
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function restore_tables(block, table_names, column_titles)
 | 
					 | 
				
			||||||
    % Восстанавливает первый столбец в каждой таблице из массива имен
 | 
					 | 
				
			||||||
    % Использует массив column_titles для установки имени столбца
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    % Получить объект маски блока
 | 
					 | 
				
			||||||
    maskObj = Simulink.Mask.get(block);
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    for k = 1:numel(table_names)
 | 
					 | 
				
			||||||
        table_name = table_names{k};
 | 
					 | 
				
			||||||
        title = column_titles{k};
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        % Получить объект управления таблицей
 | 
					 | 
				
			||||||
        tableControl = maskObj.getDialogControl(table_name);
 | 
					 | 
				
			||||||
        
 | 
					 | 
				
			||||||
        % Добавить новый столбец
 | 
					 | 
				
			||||||
        column = tableControl.addColumn(Name='title', Type='edit');
 | 
					 | 
				
			||||||
        column.Name = title;
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function tab = find_tab_by_name(controls, targetName)
 | 
					 | 
				
			||||||
    tab = [];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for i = 1:numel(controls)
 | 
					 | 
				
			||||||
        ctrl = controls(i);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        % Проверяем, вкладка ли это и совпадает ли имя
 | 
					 | 
				
			||||||
        if isa(ctrl, 'Simulink.dialog.Tab') && strcmp(ctrl.Name, targetName)
 | 
					 | 
				
			||||||
            tab = ctrl;
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        % Если это контейнер — обходим его детей
 | 
					 | 
				
			||||||
        children = get_children(ctrl);
 | 
					 | 
				
			||||||
        if ~isempty(children)
 | 
					 | 
				
			||||||
            tab = find_tab_by_name(children, targetName);
 | 
					 | 
				
			||||||
            if ~isempty(tab)
 | 
					 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function container = find_container_by_name(controls, targetName)
 | 
					 | 
				
			||||||
    container = [];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    for i = 1:numel(controls)
 | 
					 | 
				
			||||||
        ctrl = controls(i);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        % Проверяем, контейнер ли это и совпадает ли имя
 | 
					 | 
				
			||||||
        if isa(ctrl, 'Simulink.dialog.Container') && strcmp(ctrl.Name, targetName)
 | 
					 | 
				
			||||||
            container = ctrl;
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        % Если это вложенный контрол — обходим его детей
 | 
					 | 
				
			||||||
        children = get_children(ctrl);
 | 
					 | 
				
			||||||
        if ~isempty(children)
 | 
					 | 
				
			||||||
            container = find_container_by_name(children, targetName);
 | 
					 | 
				
			||||||
            if ~isempty(container)
 | 
					 | 
				
			||||||
                return;
 | 
					 | 
				
			||||||
            end
 | 
					 | 
				
			||||||
        end
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
function children = get_children(ctrl)
 | 
					 | 
				
			||||||
    if isprop(ctrl, 'DialogControls')
 | 
					 | 
				
			||||||
        children = ctrl.DialogControls;
 | 
					 | 
				
			||||||
    elseif isprop(ctrl, 'Controls')
 | 
					 | 
				
			||||||
        children = ctrl.Controls;
 | 
					 | 
				
			||||||
    elseif isprop(ctrl, 'Children')
 | 
					 | 
				
			||||||
        children = ctrl.Children;
 | 
					 | 
				
			||||||
    else
 | 
					 | 
				
			||||||
        children = [];
 | 
					 | 
				
			||||||
    end
 | 
					 | 
				
			||||||
end
 | 
					 | 
				
			||||||
@ -1,252 +0,0 @@
 | 
				
			|||||||
{
 | 
					 | 
				
			||||||
  "RCC": {
 | 
					 | 
				
			||||||
    "Defines": {
 | 
					 | 
				
			||||||
      "HCLK_Clock": {
 | 
					 | 
				
			||||||
        "Prompt": "HCLK Clock (Hz)",
 | 
					 | 
				
			||||||
        "Def": "HCLK_Value",
 | 
					 | 
				
			||||||
        "Type": "edit",
 | 
					 | 
				
			||||||
        "Default": 7.2E+7,
 | 
					 | 
				
			||||||
        "NewRow": true
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "ABP1_Clock": {
 | 
					 | 
				
			||||||
        "Prompt": "ABP1 Clock (Hz)",
 | 
					 | 
				
			||||||
        "Def": "ABP1_Value",
 | 
					 | 
				
			||||||
        "Type": "edit",
 | 
					 | 
				
			||||||
        "Default": 7.2E+7,
 | 
					 | 
				
			||||||
        "NewRow": true
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "ABP1_TIMS_Clock": {
 | 
					 | 
				
			||||||
        "Prompt": "ABP1 Tim's Clock (Hz)",
 | 
					 | 
				
			||||||
        "Def": "ABP1_TIMS_Value",
 | 
					 | 
				
			||||||
        "Type": "edit",
 | 
					 | 
				
			||||||
        "Default": 7.2E+7,
 | 
					 | 
				
			||||||
        "NewRow": true
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "ABP2_Clock": {
 | 
					 | 
				
			||||||
        "Prompt": "ABP2 Clock (Hz)",
 | 
					 | 
				
			||||||
        "Def": "ABP2_Value",
 | 
					 | 
				
			||||||
        "Type": "edit",
 | 
					 | 
				
			||||||
        "Default": 7.2E+7,
 | 
					 | 
				
			||||||
        "NewRow": true
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "ABP2_TIMS_Clock": {
 | 
					 | 
				
			||||||
        "Prompt": "ABP2 Tim's Clock (Hz)",
 | 
					 | 
				
			||||||
        "Def": "ABP2_TIMS_Value",
 | 
					 | 
				
			||||||
        "Type": "edit",
 | 
					 | 
				
			||||||
        "Default": 7.2E+7,
 | 
					 | 
				
			||||||
        "NewRow": true
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
  "TIM": {
 | 
					 | 
				
			||||||
    "Defines": {
 | 
					 | 
				
			||||||
      "TIM1_Enable": {
 | 
					 | 
				
			||||||
        "Prompt": "TIM1 Enable",
 | 
					 | 
				
			||||||
        "Def": "USE_TIM1",
 | 
					 | 
				
			||||||
        "Type": "checkbox",
 | 
					 | 
				
			||||||
        "Default": false,
 | 
					 | 
				
			||||||
        "NewRow": true
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "TIM1_UP_TIM10_Handler": {
 | 
					 | 
				
			||||||
        "Prompt": "TIM1_UP_TIM10 Handler",
 | 
					 | 
				
			||||||
        "Def": "USE_TIM1_UP_TIM10_HANDLER",
 | 
					 | 
				
			||||||
        "Type": "checkbox",
 | 
					 | 
				
			||||||
        "Default": false,
 | 
					 | 
				
			||||||
        "NewRow": false
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "TIM2_Enable": {
 | 
					 | 
				
			||||||
        "Prompt": "TIM2 Enable",
 | 
					 | 
				
			||||||
        "Def": "USE_TIM2",
 | 
					 | 
				
			||||||
        "Type": "checkbox",
 | 
					 | 
				
			||||||
        "Default": true,
 | 
					 | 
				
			||||||
        "NewRow": true
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "TIM2_Handler": {
 | 
					 | 
				
			||||||
        "Prompt": "TIM2 Handler",
 | 
					 | 
				
			||||||
        "Def": "USE_TIM2_HANDLER",
 | 
					 | 
				
			||||||
        "Type": "checkbox",
 | 
					 | 
				
			||||||
        "Default": false,
 | 
					 | 
				
			||||||
        "NewRow": false
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "TIM3_Enable": {
 | 
					 | 
				
			||||||
        "Prompt": "TIM3 Enable",
 | 
					 | 
				
			||||||
        "Def": "USE_TIM3",
 | 
					 | 
				
			||||||
        "Type": "checkbox",
 | 
					 | 
				
			||||||
        "Default": false,
 | 
					 | 
				
			||||||
        "NewRow": true
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "TIM3_Handler": {
 | 
					 | 
				
			||||||
        "Prompt": "TIM3 Handler",
 | 
					 | 
				
			||||||
        "Def": "USE_TIM3_HANDLER",
 | 
					 | 
				
			||||||
        "Type": "checkbox",
 | 
					 | 
				
			||||||
        "Default": false,
 | 
					 | 
				
			||||||
        "NewRow": false
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "TIM4_Enable": {
 | 
					 | 
				
			||||||
        "Prompt": "TIM4 Enable",
 | 
					 | 
				
			||||||
        "Def": "USE_TIM4",
 | 
					 | 
				
			||||||
        "Type": "checkbox",
 | 
					 | 
				
			||||||
        "Default": false,
 | 
					 | 
				
			||||||
        "NewRow": true
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "TIM4_Handler": {
 | 
					 | 
				
			||||||
        "Prompt": "TIM4 Handler",
 | 
					 | 
				
			||||||
        "Def": "USE_TIM4_HANDLER",
 | 
					 | 
				
			||||||
        "Type": "checkbox",
 | 
					 | 
				
			||||||
        "Default": false,
 | 
					 | 
				
			||||||
        "NewRow": false
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "TIM5_Enable": {
 | 
					 | 
				
			||||||
        "Prompt": "TIM5 Enable",
 | 
					 | 
				
			||||||
        "Def": "USE_TIM5",
 | 
					 | 
				
			||||||
        "Type": "checkbox",
 | 
					 | 
				
			||||||
        "Default": false,
 | 
					 | 
				
			||||||
        "NewRow": true
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "TIM5_Handler": {
 | 
					 | 
				
			||||||
        "Prompt": "TIM5 Handler",
 | 
					 | 
				
			||||||
        "Def": "USE_TIM5_HANDLER",
 | 
					 | 
				
			||||||
        "Type": "checkbox",
 | 
					 | 
				
			||||||
        "Default": false,
 | 
					 | 
				
			||||||
        "NewRow": false
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "TIM6_Enable": {
 | 
					 | 
				
			||||||
        "Prompt": "TIM6 Enable",
 | 
					 | 
				
			||||||
        "Def": "USE_TIM6",
 | 
					 | 
				
			||||||
        "Type": "checkbox",
 | 
					 | 
				
			||||||
        "Default": false,
 | 
					 | 
				
			||||||
        "NewRow": true
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "TIM6_Handler": {
 | 
					 | 
				
			||||||
        "Prompt": "TIM6 Handler",
 | 
					 | 
				
			||||||
        "Def": "USE_TIM6_HANDLER",
 | 
					 | 
				
			||||||
        "Type": "checkbox",
 | 
					 | 
				
			||||||
        "Default": false,
 | 
					 | 
				
			||||||
        "NewRow": false
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "TIM7_Enable": {
 | 
					 | 
				
			||||||
        "Prompt": "TIM7 Enable",
 | 
					 | 
				
			||||||
        "Def": "USE_TIM7",
 | 
					 | 
				
			||||||
        "Type": "checkbox",
 | 
					 | 
				
			||||||
        "Default": false,
 | 
					 | 
				
			||||||
        "NewRow": true
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "TIM7_Handler": {
 | 
					 | 
				
			||||||
        "Prompt": "TIM7 Handler",
 | 
					 | 
				
			||||||
        "Def": "USE_TIM7_HANDLER",
 | 
					 | 
				
			||||||
        "Type": "checkbox",
 | 
					 | 
				
			||||||
        "Default": false,
 | 
					 | 
				
			||||||
        "NewRow": false
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "TIM8_Enable": {
 | 
					 | 
				
			||||||
        "Prompt": "TIM8 Enable",
 | 
					 | 
				
			||||||
        "Def": "USE_TIM8",
 | 
					 | 
				
			||||||
        "Type": "checkbox",
 | 
					 | 
				
			||||||
        "Default": false,
 | 
					 | 
				
			||||||
        "NewRow": true
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "TIM8_UP_TIM13_Handler": {
 | 
					 | 
				
			||||||
        "Prompt": "TIM8_UP_TIM13 Handler",
 | 
					 | 
				
			||||||
        "Def": "USE_TIM8_UP_TIM13_HANDLER",
 | 
					 | 
				
			||||||
        "Type": "checkbox",
 | 
					 | 
				
			||||||
        "Default": false,
 | 
					 | 
				
			||||||
        "NewRow": false
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "TIM9_Enable": {
 | 
					 | 
				
			||||||
        "Prompt": "TIM9 Enable",
 | 
					 | 
				
			||||||
        "Def": "USE_TIM9",
 | 
					 | 
				
			||||||
        "Type": "checkbox",
 | 
					 | 
				
			||||||
        "Default": false,
 | 
					 | 
				
			||||||
        "NewRow": true
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "TIM1_BRK_TIM9_Handler": {
 | 
					 | 
				
			||||||
        "Prompt": "TIM1_BRK_TIM9 Handler",
 | 
					 | 
				
			||||||
        "Def": "USE_TIM1_BRK_TIM9_HANDLER",
 | 
					 | 
				
			||||||
        "Type": "checkbox",
 | 
					 | 
				
			||||||
        "Default": false,
 | 
					 | 
				
			||||||
        "NewRow": false
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "TIM10_Enable": {
 | 
					 | 
				
			||||||
        "Prompt": "TIM10 Enable",
 | 
					 | 
				
			||||||
        "Def": "USE_TIM10",
 | 
					 | 
				
			||||||
        "Type": "checkbox",
 | 
					 | 
				
			||||||
        "Default": false,
 | 
					 | 
				
			||||||
        "NewRow": true
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "TIM11_Enable": {
 | 
					 | 
				
			||||||
        "Prompt": "TIM11 Enable",
 | 
					 | 
				
			||||||
        "Def": "USE_TIM11",
 | 
					 | 
				
			||||||
        "Type": "checkbox",
 | 
					 | 
				
			||||||
        "Default": false,
 | 
					 | 
				
			||||||
        "NewRow": true
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "TIM1_TRG_COM_TIM11_Handler": {
 | 
					 | 
				
			||||||
        "Prompt": "TIM1_TRG_COM_TIM11 Handler",
 | 
					 | 
				
			||||||
        "Def": "USE_TIM1_TRG_COM_TIM11_HANDLER",
 | 
					 | 
				
			||||||
        "Type": "checkbox",
 | 
					 | 
				
			||||||
        "Default": false,
 | 
					 | 
				
			||||||
        "NewRow": false
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "TIM12_Enable": {
 | 
					 | 
				
			||||||
        "Prompt": "TIM12 Enable",
 | 
					 | 
				
			||||||
        "Def": "USE_TIM12",
 | 
					 | 
				
			||||||
        "Type": "checkbox",
 | 
					 | 
				
			||||||
        "Default": false,
 | 
					 | 
				
			||||||
        "NewRow": true
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "TIM8_BRK_TIM12_Handler": {
 | 
					 | 
				
			||||||
        "Prompt": "TIM8_BRK_TIM12 Handler",
 | 
					 | 
				
			||||||
        "Def": "USE_TIM8_BRK_TIM12_HANDLER",
 | 
					 | 
				
			||||||
        "Type": "checkbox",
 | 
					 | 
				
			||||||
        "Default": false,
 | 
					 | 
				
			||||||
        "NewRow": false
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "TIM13_Enable": {
 | 
					 | 
				
			||||||
        "Prompt": "TIM13 Enable",
 | 
					 | 
				
			||||||
        "Def": "USE_TIM13",
 | 
					 | 
				
			||||||
        "Type": "checkbox",
 | 
					 | 
				
			||||||
        "Default": false,
 | 
					 | 
				
			||||||
        "NewRow": true
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "TIM14_Enable": {
 | 
					 | 
				
			||||||
        "Prompt": "TIM14 Enable",
 | 
					 | 
				
			||||||
        "Def": "USE_TIM14",
 | 
					 | 
				
			||||||
        "Type": "checkbox",
 | 
					 | 
				
			||||||
        "Default": false,
 | 
					 | 
				
			||||||
        "NewRow": true
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "TIM8_TRG_COM_TIM14_Handler": {
 | 
					 | 
				
			||||||
        "Prompt": "TIM8_TRG_COM_TIM14 Handler",
 | 
					 | 
				
			||||||
        "Def": "USE_TIM8_TRG_COM_TIM14_HANDLER",
 | 
					 | 
				
			||||||
        "Type": "checkbox",
 | 
					 | 
				
			||||||
        "Default": false,
 | 
					 | 
				
			||||||
        "NewRow": false
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  "ADC": {
 | 
					 | 
				
			||||||
    "Defines": {
 | 
					 | 
				
			||||||
      "ADC1_Enable": {
 | 
					 | 
				
			||||||
        "Prompt": "ADC1 Enable",
 | 
					 | 
				
			||||||
        "Def": "ADC1_ENABLE",
 | 
					 | 
				
			||||||
        "Type": "checkbox",
 | 
					 | 
				
			||||||
        "Default": true,
 | 
					 | 
				
			||||||
        "NewRow": true
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "ADC2_Enable": {
 | 
					 | 
				
			||||||
        "Prompt": "ADC2 Enable",
 | 
					 | 
				
			||||||
        "Def": "ADC2_ENABLE",
 | 
					 | 
				
			||||||
        "Type": "checkbox",
 | 
					 | 
				
			||||||
        "Default": true,
 | 
					 | 
				
			||||||
        "NewRow": true
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "Sample_Rate": {
 | 
					 | 
				
			||||||
        "Prompt": "Sample Rate (Hz)",
 | 
					 | 
				
			||||||
        "Def": "SAMPLE_RATE",
 | 
					 | 
				
			||||||
        "Type": "edit",
 | 
					 | 
				
			||||||
        "Default": 48000,
 | 
					 | 
				
			||||||
        "NewRow": true
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  },
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user