| Upphovsman | SHA1 | Meddelande | Datum |
|---|---|---|---|
|
|
c134491907 | 标记了未完成项 | 1 månad sedan |
|
|
d2ab7d6c0a | 修复了变频后计数不准的问题 | 1 månad sedan |
|
|
f4a2216504 | 变频代码 | 1 månad sedan |
|
|
a81228b629 | 加入EXT信号 | 1 månad sedan |
|
|
ec2aa94775 | 修复EXT 硬件 pending 竞态 | 1 månad sedan |
| @@ -1263,22 +1263,16 @@ | |||||
| </group> | </group> | ||||
| </group> | </group> | ||||
| <group> | <group> | ||||
| <name>PLSR</name> | |||||
| <file> | |||||
| <name>$PROJ_DIR$\..\PLSR\Inc\plsr.h</name> | |||||
| </file> | |||||
| <file> | |||||
| <name>$PROJ_DIR$\..\PLSR\Src\plsr_internal.h</name> | |||||
| </file> | |||||
| <file> | |||||
| <name>$PROJ_DIR$\..\PLSR\Src\plsr_platform.h</name> | |||||
| </file> | |||||
| <name>Modbus</name> | |||||
| <file> | <file> | ||||
| <name>$PROJ_DIR$\..\PLSR\Src\plsr_planner.h</name> | |||||
| <name>$PROJ_DIR$\..\Modbus\Src\modbus_rtu_slave.c</name> | |||||
| </file> | </file> | ||||
| <file> | <file> | ||||
| <name>$PROJ_DIR$\..\PLSR\Src\plsr_planner.c</name> | |||||
| <name>$PROJ_DIR$\..\Modbus\Inc\modbus_rtu_slave.h</name> | |||||
| </file> | </file> | ||||
| </group> | |||||
| <group> | |||||
| <name>PLSR</name> | |||||
| <file> | <file> | ||||
| <name>$PROJ_DIR$\..\PLSR\Src\plsr.c</name> | <name>$PROJ_DIR$\..\PLSR\Src\plsr.c</name> | ||||
| <configuration> | <configuration> | ||||
| @@ -1289,6 +1283,248 @@ | |||||
| <version>35</version> | <version>35</version> | ||||
| <wantNonLocal>0</wantNonLocal> | <wantNonLocal>0</wantNonLocal> | ||||
| <debug>1</debug> | <debug>1</debug> | ||||
| <option> | |||||
| <name>CCOptimizationNoSizeConstraints</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCDefines</name> | |||||
| <state>USE_HAL_DRIVER</state> | |||||
| <state>STM32F407xx</state> | |||||
| <state>PLSR_DEBUG_TIMING=1</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCPreprocFile</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCPreprocComments</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCPreprocLine</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCListCFile</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCListCMnemonics</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCListCMessages</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCListAssFile</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCListAssSource</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCEnableRemarks</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCDiagSuppress</name> | |||||
| <state></state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCDiagRemark</name> | |||||
| <state></state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCDiagWarning</name> | |||||
| <state></state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCDiagError</name> | |||||
| <state></state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCObjPrefix</name> | |||||
| <state>1</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCAllowList</name> | |||||
| <version>1</version> | |||||
| <state>11111110</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCDebugInfo</name> | |||||
| <state>1</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>IEndianMode</name> | |||||
| <state>1</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>IProcessor</name> | |||||
| <state>1</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>IExtraOptionsCheck</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>IExtraOptions</name> | |||||
| <state></state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCLangConformance</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCSignedPlainChar</name> | |||||
| <state>1</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCRequirePrototypes</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCDiagWarnAreErr</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCCompilerRuntimeInfo</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>IFpuProcessor</name> | |||||
| <state>1</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>OutputFile</name> | |||||
| <state>$FILE_BNAME$.o</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCLibConfigHeader</name> | |||||
| <state>1</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>PreInclude</name> | |||||
| <state></state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CompilerMisraOverride</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCIncludePath2</name> | |||||
| <state>$PROJ_DIR$/../USB_DEVICE/App</state> | |||||
| <state>$PROJ_DIR$/../USB_DEVICE/Target</state> | |||||
| <state>$PROJ_DIR$/../Core/Inc</state> | |||||
| <state>$PROJ_DIR$/../Drivers/STM32F4xx_HAL_Driver/Inc</state> | |||||
| <state>$PROJ_DIR$/../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy</state> | |||||
| <state>$PROJ_DIR$/../Middlewares/ST/STM32_USB_Device_Library/Core/Inc</state> | |||||
| <state>$PROJ_DIR$/../Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc</state> | |||||
| <state>$PROJ_DIR$/../Drivers/CMSIS/Device/ST/STM32F4xx/Include</state> | |||||
| <state>$PROJ_DIR$/../Drivers/CMSIS/Include</state> | |||||
| <state>$PROJ_DIR$\..\Modbus\Inc</state> | |||||
| <state>$PROJ_DIR$\..\PLSR\Inc</state> | |||||
| <state>$PROJ_DIR$\..\Middlewares\Third_Party\Micrium\Config</state> | |||||
| <state>$PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Source</state> | |||||
| <state>$PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Ports\ARM-Cortex-M4\IAR</state> | |||||
| <state>$PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uC-CPU</state> | |||||
| <state>$PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uC-CPU\ARM-Cortex-M4\IAR</state> | |||||
| <state>$PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uC-LIB</state> | |||||
| <state>$PROJ_DIR$\..\Modbus\Inc</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCStdIncCheck</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCCodeSection</name> | |||||
| <state>.text</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>IProcessorMode2</name> | |||||
| <state>1</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CompilerMisraRules98</name> | |||||
| <version>0</version> | |||||
| <state>1000111110110101101110011100111111101110011011000101110111101101100111111111111100110011111001110111001111111111111111111111111</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CompilerMisraRules04</name> | |||||
| <version>0</version> | |||||
| <state>111101110010111111111000110111111111111111111111111110010111101111010101111111111111111111111111101111111011111001111011111011111111111111111</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCPosIndRopi</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCPosIndRwpi</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCPosIndNoDynInit</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>IccLang</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>IccCDialect</name> | |||||
| <state>1</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>IccAllowVLA</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>IccStaticDestr</name> | |||||
| <state>1</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>IccCppInlineSemantics</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>IccCmsis</name> | |||||
| <state>1</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>IccFloatSemantics</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCNoLiteralPool</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCEncSource</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCEncOutput</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCEncOutputBom</name> | |||||
| <state>1</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCEncInput</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>IccExceptions2</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>IccRTTI2</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | <option> | ||||
| <name>CCOptLevel</name> | <name>CCOptLevel</name> | ||||
| <state>3</state> | <state>3</state> | ||||
| @@ -1311,6 +1547,21 @@ | |||||
| </settings> | </settings> | ||||
| </configuration> | </configuration> | ||||
| </file> | </file> | ||||
| <file> | |||||
| <name>$PROJ_DIR$\..\PLSR\Inc\plsr.h</name> | |||||
| </file> | |||||
| <file> | |||||
| <name>$PROJ_DIR$\..\PLSR\Src\plsr_internal.h</name> | |||||
| </file> | |||||
| <file> | |||||
| <name>$PROJ_DIR$\..\PLSR\Src\plsr_planner.c</name> | |||||
| </file> | |||||
| <file> | |||||
| <name>$PROJ_DIR$\..\PLSR\Src\plsr_planner.h</name> | |||||
| </file> | |||||
| <file> | |||||
| <name>$PROJ_DIR$\..\PLSR\Src\plsr_platform.h</name> | |||||
| </file> | |||||
| <file> | <file> | ||||
| <name>$PROJ_DIR$\..\PLSR\Src\plsr_platform_f407.c</name> | <name>$PROJ_DIR$\..\PLSR\Src\plsr_platform_f407.c</name> | ||||
| <configuration> | <configuration> | ||||
| @@ -1321,6 +1572,248 @@ | |||||
| <version>35</version> | <version>35</version> | ||||
| <wantNonLocal>0</wantNonLocal> | <wantNonLocal>0</wantNonLocal> | ||||
| <debug>1</debug> | <debug>1</debug> | ||||
| <option> | |||||
| <name>CCOptimizationNoSizeConstraints</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCDefines</name> | |||||
| <state>USE_HAL_DRIVER</state> | |||||
| <state>STM32F407xx</state> | |||||
| <state>PLSR_DEBUG_TIMING=1</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCPreprocFile</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCPreprocComments</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCPreprocLine</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCListCFile</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCListCMnemonics</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCListCMessages</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCListAssFile</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCListAssSource</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCEnableRemarks</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCDiagSuppress</name> | |||||
| <state></state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCDiagRemark</name> | |||||
| <state></state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCDiagWarning</name> | |||||
| <state></state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCDiagError</name> | |||||
| <state></state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCObjPrefix</name> | |||||
| <state>1</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCAllowList</name> | |||||
| <version>1</version> | |||||
| <state>11111110</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCDebugInfo</name> | |||||
| <state>1</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>IEndianMode</name> | |||||
| <state>1</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>IProcessor</name> | |||||
| <state>1</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>IExtraOptionsCheck</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>IExtraOptions</name> | |||||
| <state></state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCLangConformance</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCSignedPlainChar</name> | |||||
| <state>1</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCRequirePrototypes</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCDiagWarnAreErr</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCCompilerRuntimeInfo</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>IFpuProcessor</name> | |||||
| <state>1</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>OutputFile</name> | |||||
| <state>$FILE_BNAME$.o</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCLibConfigHeader</name> | |||||
| <state>1</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>PreInclude</name> | |||||
| <state></state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CompilerMisraOverride</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCIncludePath2</name> | |||||
| <state>$PROJ_DIR$/../USB_DEVICE/App</state> | |||||
| <state>$PROJ_DIR$/../USB_DEVICE/Target</state> | |||||
| <state>$PROJ_DIR$/../Core/Inc</state> | |||||
| <state>$PROJ_DIR$/../Drivers/STM32F4xx_HAL_Driver/Inc</state> | |||||
| <state>$PROJ_DIR$/../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy</state> | |||||
| <state>$PROJ_DIR$/../Middlewares/ST/STM32_USB_Device_Library/Core/Inc</state> | |||||
| <state>$PROJ_DIR$/../Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc</state> | |||||
| <state>$PROJ_DIR$/../Drivers/CMSIS/Device/ST/STM32F4xx/Include</state> | |||||
| <state>$PROJ_DIR$/../Drivers/CMSIS/Include</state> | |||||
| <state>$PROJ_DIR$\..\Modbus\Inc</state> | |||||
| <state>$PROJ_DIR$\..\PLSR\Inc</state> | |||||
| <state>$PROJ_DIR$\..\Middlewares\Third_Party\Micrium\Config</state> | |||||
| <state>$PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Source</state> | |||||
| <state>$PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uCOS-II\Ports\ARM-Cortex-M4\IAR</state> | |||||
| <state>$PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uC-CPU</state> | |||||
| <state>$PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uC-CPU\ARM-Cortex-M4\IAR</state> | |||||
| <state>$PROJ_DIR$\..\Middlewares\Third_Party\Micrium\uC-LIB</state> | |||||
| <state>$PROJ_DIR$\..\Modbus\Inc</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCStdIncCheck</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCCodeSection</name> | |||||
| <state>.text</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>IProcessorMode2</name> | |||||
| <state>1</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CompilerMisraRules98</name> | |||||
| <version>0</version> | |||||
| <state>1000111110110101101110011100111111101110011011000101110111101101100111111111111100110011111001110111001111111111111111111111111</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CompilerMisraRules04</name> | |||||
| <version>0</version> | |||||
| <state>111101110010111111111000110111111111111111111111111110010111101111010101111111111111111111111111101111111011111001111011111011111111111111111</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCPosIndRopi</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCPosIndRwpi</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCPosIndNoDynInit</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>IccLang</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>IccCDialect</name> | |||||
| <state>1</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>IccAllowVLA</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>IccStaticDestr</name> | |||||
| <state>1</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>IccCppInlineSemantics</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>IccCmsis</name> | |||||
| <state>1</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>IccFloatSemantics</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCNoLiteralPool</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCEncSource</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCEncOutput</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCEncOutputBom</name> | |||||
| <state>1</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>CCEncInput</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>IccExceptions2</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | |||||
| <name>IccRTTI2</name> | |||||
| <state>0</state> | |||||
| </option> | |||||
| <option> | <option> | ||||
| <name>CCOptLevel</name> | <name>CCOptLevel</name> | ||||
| <state>3</state> | <state>3</state> | ||||
| @@ -1344,13 +1837,4 @@ | |||||
| </configuration> | </configuration> | ||||
| </file> | </file> | ||||
| </group> | </group> | ||||
| <group> | |||||
| <name>Modbus</name> | |||||
| <file> | |||||
| <name>$PROJ_DIR$\..\Modbus\Src\modbus_rtu_slave.c</name> | |||||
| </file> | |||||
| <file> | |||||
| <name>$PROJ_DIR$\..\Modbus\Inc\modbus_rtu_slave.h</name> | |||||
| </file> | |||||
| </group> | |||||
| </project> | </project> | ||||
| @@ -111,8 +111,12 @@ def plot_show(path, fs, thresh, ymax, save_path=None): | |||||
| fig, ax = plt.subplots(figsize=(15, 7)) | fig, ax = plt.subplots(figsize=(15, 7)) | ||||
| fig.subplots_adjust(bottom=0.10, top=0.92) | fig.subplots_adjust(bottom=0.10, top=0.92) | ||||
| # 全脉冲散点 | |||||
| ax.plot(t * 1000, freq, '.', ms=1.5, color='C0', alpha=0.5, zorder=1) | |||||
| # 全脉冲散点:复用 artist,重绘时按可见范围抽稀(大文件流畅) | |||||
| MAX_VISIBLE_POINTS = 5000 # 可见范围内最多绘制的点数,超过则等间隔抽稀 | |||||
| (scatter,) = ax.plot([], [], '.', ms=1.5, color='C0', alpha=0.5, zorder=1) | |||||
| tx_ms = t * 1000 | |||||
| x_full = tx_ms | |||||
| y_full = freq | |||||
| ax.set_xlim(0.0, (t[-1] + hi_w[-1]) * 1000 * 1.02) | ax.set_xlim(0.0, (t[-1] + hi_w[-1]) * 1000 * 1.02) | ||||
| ax.set_ylim(0, ymax if ymax > 0 else freq.max() * 1.08) | ax.set_ylim(0, ymax if ymax > 0 else freq.max() * 1.08) | ||||
| ax.set_title("%s 时频曲线(%d 脉冲,活动时长 %.0f ms)" % ( | ax.set_title("%s 时频曲线(%d 脉冲,活动时长 %.0f ms)" % ( | ||||
| @@ -145,6 +149,19 @@ def plot_show(path, fs, thresh, ymax, save_path=None): | |||||
| zorder=6, visible=False) | zorder=6, visible=False) | ||||
| hover_last = {'idx': -1, 'visible': False} | hover_last = {'idx': -1, 'visible': False} | ||||
| # 可见范围内抽稀绘制散点(大文件性能优化) | |||||
| def update_scatter(): | |||||
| x0, x1 = ax.get_xlim() | |||||
| mask = (x_full >= x0) & (x_full <= x1) | |||||
| n_vis = int(np.count_nonzero(mask)) | |||||
| if n_vis > MAX_VISIBLE_POINTS: | |||||
| # 等间隔抽稀:取 n_vis 中的 MAX_VISIBLE_POINTS 个 | |||||
| step = (n_vis + MAX_VISIBLE_POINTS - 1) // MAX_VISIBLE_POINTS | |||||
| idx = np.flatnonzero(mask)[::step] | |||||
| else: | |||||
| idx = np.flatnonzero(mask) | |||||
| scatter.set_data(x_full[idx], y_full[idx]) | |||||
| def on_scroll(event): | def on_scroll(event): | ||||
| if event.inaxes is not ax or event.xdata is None: | if event.inaxes is not ax or event.xdata is None: | ||||
| return | return | ||||
| @@ -167,6 +184,7 @@ def plot_show(path, fs, thresh, ymax, save_path=None): | |||||
| if n1 - n0 < 1e-6: | if n1 - n0 < 1e-6: | ||||
| return | return | ||||
| ax.set_xlim(n0, n1) | ax.set_xlim(n0, n1) | ||||
| update_scatter() | |||||
| fig.canvas.draw_idle() | fig.canvas.draw_idle() | ||||
| def on_press(event): | def on_press(event): | ||||
| @@ -187,28 +205,29 @@ def plot_show(path, fs, thresh, ymax, save_path=None): | |||||
| dy = event.ydata - state['press_y'] | dy = event.ydata - state['press_y'] | ||||
| ax.set_xlim(x0 - dx, x1 - dx) | ax.set_xlim(x0 - dx, x1 - dx) | ||||
| ax.set_ylim(y0 - dy, y1 - dy) | ax.set_ylim(y0 - dy, y1 - dy) | ||||
| update_scatter() | |||||
| fig.canvas.draw_idle() | fig.canvas.draw_idle() | ||||
| return | return | ||||
| # 悬停:找可见范围内距鼠标最近的脉冲点(屏幕像素距离 < 20px 才高亮) | # 悬停:找可见范围内距鼠标最近的脉冲点(屏幕像素距离 < 20px 才高亮) | ||||
| x0, x1 = ax.get_xlim() | x0, x1 = ax.get_xlim() | ||||
| tx_ms = t * 1000 | |||||
| mask = (tx_ms >= x0) & (tx_ms <= x1) | |||||
| mask = (x_full >= x0) & (x_full <= x1) | |||||
| if not np.any(mask): | if not np.any(mask): | ||||
| hl_marker.set_visible(False) | |||||
| hl_text.set_visible(False) | |||||
| if hover_last['visible']: | |||||
| hl_marker.set_visible(False) | |||||
| hl_text.set_visible(False) | |||||
| fig.canvas.draw_idle() | |||||
| hover_last['visible'] = False | hover_last['visible'] = False | ||||
| fig.canvas.draw_idle() | |||||
| return | return | ||||
| px, py = ax.transData.transform(np.column_stack([tx_ms[mask], freq[mask]])).T | |||||
| px, py = ax.transData.transform(np.column_stack([x_full[mask], y_full[mask]])).T | |||||
| dist = np.hypot(px - event.x, py - event.y) | dist = np.hypot(px - event.x, py - event.y) | ||||
| k = int(np.argmin(dist)) | k = int(np.argmin(dist)) | ||||
| if dist[k] <= 20.0: | if dist[k] <= 20.0: | ||||
| idx = int(np.flatnonzero(mask)[k]) | idx = int(np.flatnonzero(mask)[k]) | ||||
| hl_marker.set_data([tx_ms[idx]], [freq[idx]]) | |||||
| hl_marker.set_data([x_full[idx]], [y_full[idx]]) | |||||
| hl_text.set_text("脉冲 #%d\nt = %.3f ms\nf = %.0f Hz" | hl_text.set_text("脉冲 #%d\nt = %.3f ms\nf = %.0f Hz" | ||||
| % (idx + 1, tx_ms[idx], freq[idx])) | |||||
| hl_text.set_position((tx_ms[idx] + (x1 - x0) * 0.01, | |||||
| freq[idx] + (ax.get_ylim()[1] - ax.get_ylim()[0]) * 0.02)) | |||||
| % (idx + 1, x_full[idx], y_full[idx])) | |||||
| hl_text.set_position((x_full[idx] + (x1 - x0) * 0.01, | |||||
| y_full[idx] + (ax.get_ylim()[1] - ax.get_ylim()[0]) * 0.02)) | |||||
| hl_marker.set_visible(True) | hl_marker.set_visible(True) | ||||
| hl_text.set_visible(True) | hl_text.set_visible(True) | ||||
| if hover_last['idx'] != idx or not hover_last['visible']: | if hover_last['idx'] != idx or not hover_last['visible']: | ||||
| @@ -229,8 +248,10 @@ def plot_show(path, fs, thresh, ymax, save_path=None): | |||||
| if event.dblclick: | if event.dblclick: | ||||
| ax.set_xlim(0.0, (t[-1] + hi_w[-1]) * 1000 * 1.02) | ax.set_xlim(0.0, (t[-1] + hi_w[-1]) * 1000 * 1.02) | ||||
| ax.set_ylim(0, ymax if ymax > 0 else freq.max() * 1.08) | ax.set_ylim(0, ymax if ymax > 0 else freq.max() * 1.08) | ||||
| update_scatter() | |||||
| fig.canvas.draw_idle() | fig.canvas.draw_idle() | ||||
| update_scatter() | |||||
| fig.canvas.mpl_connect('scroll_event', on_scroll) | fig.canvas.mpl_connect('scroll_event', on_scroll) | ||||
| fig.canvas.mpl_connect('button_press_event', on_press) | fig.canvas.mpl_connect('button_press_event', on_press) | ||||
| fig.canvas.mpl_connect('button_release_event', on_release) | fig.canvas.mpl_connect('button_release_event', on_release) | ||||
| @@ -93,7 +93,9 @@ uint8_t PlsrPlatformRequestFiniteCut(uint8_t pulseOutput); | |||||
| uint8_t PlsrPlatformFiniteRetargetReady(uint8_t pulseOutput, | uint8_t PlsrPlatformFiniteRetargetReady(uint8_t pulseOutput, | ||||
| uint32_t *activeFrequencyHz); | uint32_t *activeFrequencyHz); | ||||
| uint8_t PlsrPlatformFinitePipelineSnapshot(uint8_t pulseOutput, | uint8_t PlsrPlatformFinitePipelineSnapshot(uint8_t pulseOutput, | ||||
| uint64_t *observedPulses, | |||||
| uint32_t *committedPulses, | uint32_t *committedPulses, | ||||
| uint64_t *committedTimeUs, | |||||
| uint32_t *tailFrequencyHz, | uint32_t *tailFrequencyHz, | ||||
| uint8_t *startsNextSegment); | uint8_t *startsNextSegment); | ||||
| uint8_t PlsrPlatformFiniteProgress(uint8_t pulseOutput, | uint8_t PlsrPlatformFiniteProgress(uint8_t pulseOutput, | ||||
| @@ -118,7 +120,7 @@ uint8_t PlsrExecTakeCountedRunIrq( | |||||
| void PlsrExecCountedSegmentBoundaryIrq(uint8_t pulseOutput, | void PlsrExecCountedSegmentBoundaryIrq(uint8_t pulseOutput, | ||||
| uint32_t completedPulses); | uint32_t completedPulses); | ||||
| void PlsrExecCountedStreamFaultIrq(uint8_t pulseOutput); | void PlsrExecCountedStreamFaultIrq(uint8_t pulseOutput); | ||||
| /* EXTI callback: records only an armed WAIT input edge. */ | |||||
| /* EXTI callback: records an armed WAIT or active EXT input edge. */ | |||||
| void PlsrWaitInputExtiIrq(uint8_t inputSelection); | void PlsrWaitInputExtiIrq(uint8_t inputSelection); | ||||
| PLSR_PLATFORM_QUEUE_RESULT PlsrPlatformLoadPreparedFromIrq( | PLSR_PLATFORM_QUEUE_RESULT PlsrPlatformLoadPreparedFromIrq( | ||||
| uint8_t pulseOutput, | uint8_t pulseOutput, | ||||
| @@ -145,6 +147,9 @@ PLSR_PLATFORM_STOP_RESULT PlsrPlatformRequestStopLocked( | |||||
| uint8_t PlsrPlatformQueueFinalArmFromIrq(uint8_t pulseOutput); | uint8_t PlsrPlatformQueueFinalArmFromIrq(uint8_t pulseOutput); | ||||
| void PlsrPlatformStopPulse(uint8_t pulseOutput); | void PlsrPlatformStopPulse(uint8_t pulseOutput); | ||||
| uint8_t PlsrPlatformReadInput(uint8_t inputSelection); | uint8_t PlsrPlatformReadInput(uint8_t inputSelection); | ||||
| /* Called from the counted-boundary IRQ before the EXT capture context moves | |||||
| to the next segment. Returns and clears a rising edge pending in EXTI. */ | |||||
| uint8_t PlsrPlatformTakeInputExtiPending(uint8_t inputSelection); | |||||
| uint8_t PlsrPlatformLoad(PLSR_PERSIST_PAYLOAD *payload); | uint8_t PlsrPlatformLoad(PLSR_PERSIST_PAYLOAD *payload); | ||||
| PLSR_PLATFORM_SERVICE_RESULT PlsrPlatformServicePersistence(void); | PLSR_PLATFORM_SERVICE_RESULT PlsrPlatformServicePersistence(void); | ||||
| @@ -551,22 +551,35 @@ uint8_t PlsrPlatformFiniteRetargetReady(uint8_t pulseOutput, | |||||
| } | } | ||||
| uint8_t PlsrPlatformFinitePipelineSnapshot(uint8_t pulseOutput, | uint8_t PlsrPlatformFinitePipelineSnapshot(uint8_t pulseOutput, | ||||
| uint64_t *observedPulses, | |||||
| uint32_t *committedPulses, | uint32_t *committedPulses, | ||||
| uint64_t *committedTimeUs, | |||||
| uint32_t *tailFrequencyHz, | uint32_t *tailFrequencyHz, | ||||
| uint8_t *startsNextSegment) | uint8_t *startsNextSegment) | ||||
| { | { | ||||
| uint32_t remaining; | uint32_t remaining; | ||||
| uint32_t frequencyHz; | |||||
| if ((pulseOutput > 3U) || (committedPulses == NULL) | |||||
| || (tailFrequencyHz == NULL) || (startsNextSegment == NULL) | |||||
| if ((pulseOutput > 3U) || (observedPulses == NULL) | |||||
| || (committedPulses == NULL) | |||||
| || (committedTimeUs == NULL) || (tailFrequencyHz == NULL) | |||||
| || (startsNextSegment == NULL) | |||||
| || (PlsrHostFiniteActive[pulseOutput] == 0U)) | || (PlsrHostFiniteActive[pulseOutput] == 0U)) | ||||
| { | { | ||||
| return 0U; | return 0U; | ||||
| } | } | ||||
| remaining = PlsrHostFiniteTarget[pulseOutput] | remaining = PlsrHostFiniteTarget[pulseOutput] | ||||
| - PlsrHostFiniteEmitted[pulseOutput]; | - PlsrHostFiniteEmitted[pulseOutput]; | ||||
| frequencyHz = PlsrHostFrequency[pulseOutput]; | |||||
| if (frequencyHz == 0UL) | |||||
| { | |||||
| return 0U; | |||||
| } | |||||
| *observedPulses = PlsrHostObservedPulses[pulseOutput]; | |||||
| *committedPulses = remaining; | *committedPulses = remaining; | ||||
| *tailFrequencyHz = PlsrHostQueuedFrequency[pulseOutput]; | |||||
| *committedTimeUs = ((uint64_t)remaining * 1000000ULL | |||||
| + frequencyHz - 1UL) / frequencyHz; | |||||
| *tailFrequencyHz = frequencyHz; | |||||
| *startsNextSegment = 0U; | *startsNextSegment = 0U; | ||||
| return 1U; | return 1U; | ||||
| } | } | ||||
| @@ -893,6 +906,12 @@ uint8_t PlsrPlatformReadInput(uint8_t inputSelection) | |||||
| return (inputSelection <= 1U) ? PlsrHostInputs[inputSelection] : 0U; | return (inputSelection <= 1U) ? PlsrHostInputs[inputSelection] : 0U; | ||||
| } | } | ||||
| uint8_t PlsrPlatformTakeInputExtiPending(uint8_t inputSelection) | |||||
| { | |||||
| (void)inputSelection; | |||||
| return 0U; | |||||
| } | |||||
| uint8_t PlsrPlatformLoad(PLSR_PERSIST_PAYLOAD *payload) | uint8_t PlsrPlatformLoad(PLSR_PERSIST_PAYLOAD *payload) | ||||
| { | { | ||||
| if ((payload == NULL) || (PlsrHostPersistentValid == 0U)) | if ((payload == NULL) || (PlsrHostPersistentValid == 0U)) | ||||
| @@ -1574,8 +1593,8 @@ static void PlsrFiniteArmNextStepPrepare(uint8_t pulseOutput, | |||||
| TIM_TypeDef *counter, | TIM_TypeDef *counter, | ||||
| uint32_t blockPulses); | uint32_t blockPulses); | ||||
| static void PlsrFiniteRetargetAtFallingEdge(uint8_t pulseOutput); | static void PlsrFiniteRetargetAtFallingEdge(uint8_t pulseOutput); | ||||
| static void PlsrFiniteCutAtFallingEdge(uint8_t pulseOutput); | |||||
| static void PlsrFiniteStopAtFallingEdge(uint8_t pulseOutput); | |||||
| static void PlsrFiniteCutAtIdleBoundary(uint8_t pulseOutput); | |||||
| static void PlsrFiniteStopAtIdleBoundary(uint8_t pulseOutput); | |||||
| static uint8_t PlsrFinalArmJobOutput(uint8_t pulseOutput) | static uint8_t PlsrFinalArmJobOutput(uint8_t pulseOutput) | ||||
| { | { | ||||
| @@ -2364,11 +2383,86 @@ static uint64_t PlsrCounterCurrentRaw(uint8_t pulseOutput) | |||||
| } | } | ||||
| } | } | ||||
| /* Return completed pulses in the active PUL/DIR run. The one-pulse block | |||||
| preload is an implementation detail, and a pending counter update means | |||||
| the current block has completed even if its IRQ has not run yet. */ | |||||
| static uint32_t PlsrFiniteCompletedPulsesSnapshot(uint8_t pulseOutput) | |||||
| { | |||||
| uint8_t index = PlsrCounterIndexByOutput[pulseOutput]; | |||||
| TIM_TypeDef *counter; | |||||
| uint32_t target; | |||||
| uint32_t remainingBefore; | |||||
| uint32_t remainingAfter; | |||||
| uint32_t statusBefore; | |||||
| uint32_t statusAfter; | |||||
| uint32_t count; | |||||
| uint32_t blockCount; | |||||
| uint32_t completed; | |||||
| if (index >= PLSR_COUNTER_COUNT) | |||||
| { | |||||
| return 0UL; | |||||
| } | |||||
| counter = PlsrCounters[index]; | |||||
| for (;;) | |||||
| { | |||||
| remainingBefore = PlsrFiniteRemainingPulses[pulseOutput]; | |||||
| statusBefore = counter->SR & TIM_SR_UIF; | |||||
| count = (uint16_t)counter->CNT; | |||||
| statusAfter = counter->SR & TIM_SR_UIF; | |||||
| remainingAfter = PlsrFiniteRemainingPulses[pulseOutput]; | |||||
| if ((remainingBefore == remainingAfter) | |||||
| && (statusBefore == statusAfter)) | |||||
| { | |||||
| break; | |||||
| } | |||||
| } | |||||
| target = PlsrFiniteTargetPulses[pulseOutput]; | |||||
| if (remainingAfter > target) | |||||
| { | |||||
| return 0UL; | |||||
| } | |||||
| completed = target - remainingAfter; | |||||
| if (statusAfter != 0UL) | |||||
| { | |||||
| blockCount = (remainingAfter > PLSR_COUNTER_BLOCK_PULSES) | |||||
| ? PLSR_COUNTER_BLOCK_PULSES : remainingAfter; | |||||
| if (count > (remainingAfter - blockCount)) | |||||
| { | |||||
| count = remainingAfter - blockCount; | |||||
| } | |||||
| blockCount += count; | |||||
| } | |||||
| else if (count >= PlsrFiniteCounterPreload[pulseOutput]) | |||||
| { | |||||
| blockCount = count - PlsrFiniteCounterPreload[pulseOutput]; | |||||
| } | |||||
| else | |||||
| { | |||||
| blockCount = 0UL; | |||||
| } | |||||
| if (blockCount > remainingAfter) | |||||
| { | |||||
| blockCount = remainingAfter; | |||||
| } | |||||
| return completed + blockCount; | |||||
| } | |||||
| static uint64_t PlsrCounterSnapshot(uint8_t pulseOutput) | static uint64_t PlsrCounterSnapshot(uint8_t pulseOutput) | ||||
| { | { | ||||
| uint64_t current = PlsrCounterCurrentRaw(pulseOutput); | |||||
| uint64_t current; | |||||
| uint64_t observed; | uint64_t observed; | ||||
| if ((PlsrTimerOutputMode[pulseOutput] == PLSR_OUTPUT_PULSE_DIR) | |||||
| && (PlsrFiniteActive[pulseOutput] != 0U)) | |||||
| { | |||||
| current = PlsrFiniteCompletedPulsesSnapshot(pulseOutput); | |||||
| } | |||||
| else | |||||
| { | |||||
| current = PlsrCounterCurrentRaw(pulseOutput); | |||||
| } | |||||
| if ((PlsrTimerOutputMode[pulseOutput] == PLSR_OUTPUT_AB) | if ((PlsrTimerOutputMode[pulseOutput] == PLSR_OUTPUT_AB) | ||||
| && (current > 0UL)) | && (current > 0UL)) | ||||
| { | { | ||||
| @@ -3445,6 +3539,8 @@ uint8_t PlsrPlatformRetargetFiniteStop(uint8_t pulseOutput, | |||||
| uint8_t PlsrPlatformRequestFiniteCut(uint8_t pulseOutput) | uint8_t PlsrPlatformRequestFiniteCut(uint8_t pulseOutput) | ||||
| { | { | ||||
| TIM_TypeDef *timer; | TIM_TypeDef *timer; | ||||
| uint32_t timerCompare; | |||||
| uint32_t timerCount; | |||||
| uint32_t criticalState; | uint32_t criticalState; | ||||
| if (pulseOutput > 3U) | if (pulseOutput > 3U) | ||||
| @@ -3455,8 +3551,7 @@ uint8_t PlsrPlatformRequestFiniteCut(uint8_t pulseOutput) | |||||
| criticalState = PlsrPlatformEnterCritical(); | criticalState = PlsrPlatformEnterCritical(); | ||||
| if ((PlsrFiniteActive[pulseOutput] == 0U) | if ((PlsrFiniteActive[pulseOutput] == 0U) | ||||
| || (PlsrFiniteStreamActive[pulseOutput] == 0U) | || (PlsrFiniteStreamActive[pulseOutput] == 0U) | ||||
| || (PlsrCounterIndexByOutput[pulseOutput] >= PLSR_COUNTER_COUNT) | |||||
| || (PlsrFiniteRetargetPending[pulseOutput] != 0U)) | |||||
| || (PlsrCounterIndexByOutput[pulseOutput] >= PLSR_COUNTER_COUNT)) | |||||
| { | { | ||||
| PlsrPlatformExitCritical(criticalState); | PlsrPlatformExitCritical(criticalState); | ||||
| return 0U; | return 0U; | ||||
| @@ -3467,17 +3562,35 @@ uint8_t PlsrPlatformRequestFiniteCut(uint8_t pulseOutput) | |||||
| return 1U; | return 1U; | ||||
| } | } | ||||
| /* Do not allow a run already staged by the producer to cross the cut. | |||||
| CC1 reaches the physical pulse's falling edge, where the output is | |||||
| idle and can be stopped without shortening the high or low width. */ | |||||
| /* EXT supersedes an unpublished retarget and any producer-staged run. */ | |||||
| PlsrFiniteRetargetPending[pulseOutput] = 0U; | |||||
| PlsrFiniteRetargetDrainPulses[pulseOutput] = 0UL; | |||||
| PlsrFiniteStreamNextValid[pulseOutput] = 0U; | PlsrFiniteStreamNextValid[pulseOutput] = 0U; | ||||
| PlsrFiniteStreamNextStartsSegment[pulseOutput] = 0U; | PlsrFiniteStreamNextStartsSegment[pulseOutput] = 0U; | ||||
| PlsrFiniteStreamSourceDone[pulseOutput] = 1U; | PlsrFiniteStreamSourceDone[pulseOutput] = 1U; | ||||
| PlsrFiniteStreamSourceFault[pulseOutput] = 0U; | PlsrFiniteStreamSourceFault[pulseOutput] = 0U; | ||||
| PlsrFiniteTailStopPending[pulseOutput] = 1U; | PlsrFiniteTailStopPending[pulseOutput] = 1U; | ||||
| timer = PlsrTimerMap[pulseOutput].timer; | timer = PlsrTimerMap[pulseOutput].timer; | ||||
| timer->DIER &= ~TIM_DIER_CC1IE; | |||||
| timer->SR = ~TIM_SR_CC1IF; | timer->SR = ~TIM_SR_CC1IF; | ||||
| timer->DIER |= TIM_DIER_CC1IE; | |||||
| /* PWM1 is idle high before CCR1 and active low after CCR1. Freeze the | |||||
| source briefly so the phase decision cannot turn a full pulse into a | |||||
| short glitch. A low pulse is resumed and allowed to finish at update. */ | |||||
| timer->CR1 &= ~TIM_CR1_CEN; | |||||
| __DSB(); | |||||
| timerCount = timer->CNT; | |||||
| timerCompare = PlsrTimerActiveSetting[pulseOutput].compare; | |||||
| if (timerCount < timerCompare) | |||||
| { | |||||
| PlsrFiniteCutAtIdleBoundary(pulseOutput); | |||||
| } | |||||
| else | |||||
| { | |||||
| timer->SR = ~TIM_SR_UIF; | |||||
| timer->DIER |= TIM_DIER_UIE; | |||||
| timer->CR1 |= TIM_CR1_CEN; | |||||
| } | |||||
| __DMB(); | __DMB(); | ||||
| PlsrPlatformExitCritical(criticalState); | PlsrPlatformExitCritical(criticalState); | ||||
| return 1U; | return 1U; | ||||
| @@ -3503,17 +3616,23 @@ uint8_t PlsrPlatformFiniteRetargetReady(uint8_t pulseOutput, | |||||
| } | } | ||||
| uint8_t PlsrPlatformFinitePipelineSnapshot(uint8_t pulseOutput, | uint8_t PlsrPlatformFinitePipelineSnapshot(uint8_t pulseOutput, | ||||
| uint64_t *observedPulses, | |||||
| uint32_t *committedPulses, | uint32_t *committedPulses, | ||||
| uint64_t *committedTimeUs, | |||||
| uint32_t *tailFrequencyHz, | uint32_t *tailFrequencyHz, | ||||
| uint8_t *startsNextSegment) | uint8_t *startsNextSegment) | ||||
| { | { | ||||
| TIM_TypeDef *counter; | |||||
| uint32_t criticalState; | uint32_t criticalState; | ||||
| uint32_t blockCount; | |||||
| uint32_t completed; | |||||
| uint32_t frequencyHz; | |||||
| uint32_t remaining; | uint32_t remaining; | ||||
| uint64_t timeUs; | |||||
| uint64_t observed; | |||||
| if ((pulseOutput > 3U) || (committedPulses == NULL) | |||||
| || (tailFrequencyHz == NULL) || (startsNextSegment == NULL)) | |||||
| if ((pulseOutput > 3U) || (observedPulses == NULL) | |||||
| || (committedPulses == NULL) | |||||
| || (committedTimeUs == NULL) || (tailFrequencyHz == NULL) | |||||
| || (startsNextSegment == NULL)) | |||||
| { | { | ||||
| return 0U; | return 0U; | ||||
| } | } | ||||
| @@ -3525,23 +3644,31 @@ uint8_t PlsrPlatformFinitePipelineSnapshot(uint8_t pulseOutput, | |||||
| PlsrPlatformExitCritical(criticalState); | PlsrPlatformExitCritical(criticalState); | ||||
| return 0U; | return 0U; | ||||
| } | } | ||||
| counter = PlsrCounters[PlsrCounterIndexByOutput[pulseOutput]]; | |||||
| blockCount = (uint16_t)counter->CNT; | |||||
| if (blockCount >= PlsrFiniteCounterPreload[pulseOutput]) | |||||
| completed = PlsrFiniteCompletedPulsesSnapshot(pulseOutput); | |||||
| remaining = PlsrFiniteTargetPulses[pulseOutput]; | |||||
| if (completed > remaining) | |||||
| { | { | ||||
| blockCount -= PlsrFiniteCounterPreload[pulseOutput]; | |||||
| completed = remaining; | |||||
| } | |||||
| observed = PlsrObservedPulseBase[pulseOutput] + completed; | |||||
| if (observed < PlsrObservedPulsePublished[pulseOutput]) | |||||
| { | |||||
| observed = PlsrObservedPulsePublished[pulseOutput]; | |||||
| } | } | ||||
| else | else | ||||
| { | { | ||||
| blockCount = 0UL; | |||||
| PlsrObservedPulsePublished[pulseOutput] = observed; | |||||
| } | } | ||||
| remaining = PlsrFiniteRemainingPulses[pulseOutput]; | |||||
| if (blockCount > remaining) | |||||
| remaining -= completed; | |||||
| frequencyHz = PlsrTimerActiveFrequencyHz[pulseOutput]; | |||||
| if (frequencyHz == 0UL) | |||||
| { | { | ||||
| blockCount = remaining; | |||||
| PlsrPlatformExitCritical(criticalState); | |||||
| return 0U; | |||||
| } | } | ||||
| remaining -= blockCount; | |||||
| *tailFrequencyHz = PlsrTimerActiveFrequencyHz[pulseOutput]; | |||||
| timeUs = ((uint64_t)remaining * 1000000ULL | |||||
| + frequencyHz - 1UL) / frequencyHz; | |||||
| *tailFrequencyHz = frequencyHz; | |||||
| *startsNextSegment = 0U; | *startsNextSegment = 0U; | ||||
| if (PlsrFiniteStreamNextValid[pulseOutput] != 0U) | if (PlsrFiniteStreamNextValid[pulseOutput] != 0U) | ||||
| { | { | ||||
| @@ -3549,12 +3676,22 @@ uint8_t PlsrPlatformFinitePipelineSnapshot(uint8_t pulseOutput, | |||||
| remaining = (nextPulses > (0xFFFFFFFFUL - remaining)) | remaining = (nextPulses > (0xFFFFFFFFUL - remaining)) | ||||
| ? 0xFFFFFFFFUL : remaining + nextPulses; | ? 0xFFFFFFFFUL : remaining + nextPulses; | ||||
| *tailFrequencyHz = | |||||
| frequencyHz = | |||||
| PlsrFiniteStreamNextSetting[pulseOutput].actualFrequencyHz; | PlsrFiniteStreamNextSetting[pulseOutput].actualFrequencyHz; | ||||
| if (frequencyHz == 0UL) | |||||
| { | |||||
| PlsrPlatformExitCritical(criticalState); | |||||
| return 0U; | |||||
| } | |||||
| timeUs += ((uint64_t)nextPulses * 1000000ULL | |||||
| + frequencyHz - 1UL) / frequencyHz; | |||||
| *tailFrequencyHz = frequencyHz; | |||||
| *startsNextSegment = | *startsNextSegment = | ||||
| PlsrFiniteStreamNextStartsSegment[pulseOutput]; | PlsrFiniteStreamNextStartsSegment[pulseOutput]; | ||||
| } | } | ||||
| *observedPulses = observed; | |||||
| *committedPulses = remaining; | *committedPulses = remaining; | ||||
| *committedTimeUs = timeUs; | |||||
| PlsrPlatformExitCritical(criticalState); | PlsrPlatformExitCritical(criticalState); | ||||
| return 1U; | return 1U; | ||||
| } | } | ||||
| @@ -4284,6 +4421,30 @@ uint8_t PlsrPlatformReadInput(uint8_t inputSelection) | |||||
| return 0U; | return 0U; | ||||
| } | } | ||||
| uint8_t PlsrPlatformTakeInputExtiPending(uint8_t inputSelection) | |||||
| { | |||||
| uint16_t pin; | |||||
| if (inputSelection == 0U) | |||||
| { | |||||
| pin = GPIO_PIN_5; | |||||
| } | |||||
| else if (inputSelection == 1U) | |||||
| { | |||||
| pin = GPIO_PIN_12; | |||||
| } | |||||
| else | |||||
| { | |||||
| return 0U; | |||||
| } | |||||
| if (__HAL_GPIO_EXTI_GET_IT(pin) == RESET) | |||||
| { | |||||
| return 0U; | |||||
| } | |||||
| __HAL_GPIO_EXTI_CLEAR_IT(pin); | |||||
| return 1U; | |||||
| } | |||||
| uint8_t PlsrPlatformLoad(PLSR_PERSIST_PAYLOAD *payload) | uint8_t PlsrPlatformLoad(PLSR_PERSIST_PAYLOAD *payload) | ||||
| { | { | ||||
| PLSR_FLASH_SECTOR_SCAN scanA; | PLSR_FLASH_SECTOR_SCAN scanA; | ||||
| @@ -4659,7 +4820,8 @@ static void PlsrHandleTimerIrq(uint8_t pulseOutput) | |||||
| && (PlsrFiniteTailStopPending[pulseOutput] != 0U)) | && (PlsrFiniteTailStopPending[pulseOutput] != 0U)) | ||||
| { | { | ||||
| timer->SR = ~TIM_SR_CC1IF; | timer->SR = ~TIM_SR_CC1IF; | ||||
| PlsrFiniteCutAtFallingEdge(pulseOutput); | |||||
| timer->DIER &= ~TIM_DIER_CC1IE; | |||||
| timer->DIER |= TIM_DIER_UIE; | |||||
| goto irq_done; | goto irq_done; | ||||
| } | } | ||||
| #if PLSR_DEBUG_TIMING | #if PLSR_DEBUG_TIMING | ||||
| @@ -4732,6 +4894,12 @@ static void PlsrHandleTimerIrq(uint8_t pulseOutput) | |||||
| && ((timer->DIER & TIM_DIER_UIE) != 0UL)) | && ((timer->DIER & TIM_DIER_UIE) != 0UL)) | ||||
| { | { | ||||
| timer->SR = ~(TIM_SR_UIF | TIM_SR_CC1IF); | timer->SR = ~(TIM_SR_UIF | TIM_SR_CC1IF); | ||||
| if ((PlsrTimerOutputMode[pulseOutput] == PLSR_OUTPUT_PULSE_DIR) | |||||
| && (PlsrFiniteTailStopPending[pulseOutput] != 0U)) | |||||
| { | |||||
| PlsrFiniteCutAtIdleBoundary(pulseOutput); | |||||
| goto irq_done; | |||||
| } | |||||
| if ((PlsrFiniteActive[pulseOutput] != 0U) | if ((PlsrFiniteActive[pulseOutput] != 0U) | ||||
| && (PlsrFiniteFrequencyPending[pulseOutput] != 0U)) | && (PlsrFiniteFrequencyPending[pulseOutput] != 0U)) | ||||
| { | { | ||||
| @@ -5180,13 +5348,9 @@ static void PlsrFiniteCounterIrq(uint8_t pulseOutput, | |||||
| counter->CR1 &= ~TIM_CR1_CEN; | counter->CR1 &= ~TIM_CR1_CEN; | ||||
| counter->SMCR &= ~(TIM_SMCR_SMS_2 | TIM_SMCR_SMS_1 | TIM_SMCR_SMS_0); | counter->SMCR &= ~(TIM_SMCR_SMS_2 | TIM_SMCR_SMS_1 | TIM_SMCR_SMS_0); | ||||
| /* | |||||
| * An OC rising edge is the terminal pulse's falling edge because the | |||||
| * output stage is active low. The target-count update IRQ therefore is | |||||
| * already the safe idle boundary: stop here before CCR1 can start an | |||||
| * extra terminal pulse. | |||||
| */ | |||||
| PlsrFiniteStopAtFallingEdge(pulseOutput); | |||||
| /* The counter update is sourced by the PWM edge that returns the MCU pin | |||||
| high. The terminal pulse is complete and the output is safely idle. */ | |||||
| PlsrFiniteStopAtIdleBoundary(pulseOutput); | |||||
| } | } | ||||
| static void PlsrFiniteRetargetAtFallingEdge(uint8_t pulseOutput) | static void PlsrFiniteRetargetAtFallingEdge(uint8_t pulseOutput) | ||||
| @@ -5235,32 +5399,16 @@ static void PlsrFiniteRetargetAtFallingEdge(uint8_t pulseOutput) | |||||
| PlsrCounterBegin(pulseOutput); | PlsrCounterBegin(pulseOutput); | ||||
| } | } | ||||
| static void PlsrFiniteCutAtFallingEdge(uint8_t pulseOutput) | |||||
| static void PlsrFiniteCutAtIdleBoundary(uint8_t pulseOutput) | |||||
| { | { | ||||
| uint8_t counterIndex = PlsrCounterIndexByOutput[pulseOutput]; | uint8_t counterIndex = PlsrCounterIndexByOutput[pulseOutput]; | ||||
| TIM_TypeDef *counter = PlsrCounters[counterIndex]; | TIM_TypeDef *counter = PlsrCounters[counterIndex]; | ||||
| uint32_t blockCount; | |||||
| uint32_t completed; | uint32_t completed; | ||||
| /* Freeze the external counter at the same falling edge that makes the | |||||
| pulse output idle, then convert the partial current run into the | |||||
| terminal run consumed by PlsrPlatformTakeFiniteCompletion(). */ | |||||
| /* The source output is high here. Freeze the slave counter and publish | |||||
| exactly the completed full pulses from the partial current run. */ | |||||
| PlsrCounterSuspend(pulseOutput); | PlsrCounterSuspend(pulseOutput); | ||||
| blockCount = (uint16_t)counter->CNT; | |||||
| if (blockCount >= PlsrFiniteCounterPreload[pulseOutput]) | |||||
| { | |||||
| blockCount -= PlsrFiniteCounterPreload[pulseOutput]; | |||||
| } | |||||
| else | |||||
| { | |||||
| blockCount = 0UL; | |||||
| } | |||||
| completed = PlsrFiniteTargetPulses[pulseOutput] | |||||
| - PlsrFiniteRemainingPulses[pulseOutput] + blockCount; | |||||
| if (completed > PlsrFiniteTargetPulses[pulseOutput]) | |||||
| { | |||||
| completed = PlsrFiniteTargetPulses[pulseOutput]; | |||||
| } | |||||
| completed = PlsrFiniteCompletedPulsesSnapshot(pulseOutput); | |||||
| PlsrObservedPulseBase[pulseOutput] += completed; | PlsrObservedPulseBase[pulseOutput] += completed; | ||||
| PlsrObservedPulsePublished[pulseOutput] = | PlsrObservedPulsePublished[pulseOutput] = | ||||
| @@ -5276,10 +5424,10 @@ static void PlsrFiniteCutAtFallingEdge(uint8_t pulseOutput) | |||||
| PlsrCounterOverflowPulses[counterIndex] = 0UL; | PlsrCounterOverflowPulses[counterIndex] = 0UL; | ||||
| counter->CNT = 0UL; | counter->CNT = 0UL; | ||||
| counter->SR = 0UL; | counter->SR = 0UL; | ||||
| PlsrFiniteStopAtFallingEdge(pulseOutput); | |||||
| PlsrFiniteStopAtIdleBoundary(pulseOutput); | |||||
| } | } | ||||
| static void PlsrFiniteStopAtFallingEdge(uint8_t pulseOutput) | |||||
| static void PlsrFiniteStopAtIdleBoundary(uint8_t pulseOutput) | |||||
| { | { | ||||
| TIM_TypeDef *timer = PlsrTimerMap[pulseOutput].timer; | TIM_TypeDef *timer = PlsrTimerMap[pulseOutput].timer; | ||||