| @@ -30,3 +30,8 @@ tmp/ | |||
| .codex-tmp/ | |||
| Document/PLSR_document/波形/ | |||
| Document/PLSR_document/上位机图片/ | |||
| .codex_docx_qa_final5/ | |||
| .codex_docx_qa_final/ | |||
| .codex_docx_qa_final2/ | |||
| .codex_docx_qa_final4/ | |||
| .codex_docx_qa_final3/ | |||
| @@ -18,14 +18,23 @@ | |||
| python bin_to_time_freq.py xxx.bin 3125000 --save=out.png | |||
| python bin_to_time_freq.py xxx.bin 3125000 --selftest | |||
| python bin_to_time_freq.py xxx.bin 3125000 --reverse --cycles=8 | |||
| python bin_to_time_freq.py xxx.bin 3125000 --d1 --d2 | |||
| python bin_to_time_freq.py xxx.bin 3125000 --d1 --dwindow-ms=10 | |||
| python bin_to_time_freq.py xxx.bin 3125000 --d1 --d2 --d1-window-ms=5 --d2-window-ms=15 | |||
| 选项: | |||
| --thresh=128 电平阈值(默认128) | |||
| --cycles=8 用连续多少个周期估计频率(默认8;1为逐周期) | |||
| --reverse 反相电平后再检测脉冲(低电平作为脉冲高电平) | |||
| --ymax=12000 频率轴上限(默认自适应) | |||
| --d1 另开一张图:频率对时间的一阶导数 df/dt(红) | |||
| --d2 另开一张图:频率对时间的二阶导数 d²f/dt²(黑) | |||
| --dwindow-ms=5 一、二阶导数的公共拟合窗口,单位 ms(默认5) | |||
| --d1-window-ms 原函数 -> 一阶导数的拟合窗口(默认继承 --dwindow-ms) | |||
| --d2-window-ms 一阶导数 -> 二阶导数的拟合窗口(默认继承 --dwindow-ms) | |||
| --save=路径 保存 PNG 后退出(不弹窗) | |||
| --selftest 仅打印统计,不画图 | |||
| --help, -h 显示这份中文帮助后退出 | |||
| 交互(弹窗模式): | |||
| 滚轮 缩放 X 轴(向上放大/向下缩小,以鼠标位置为中心) | |||
| @@ -166,7 +175,61 @@ def selftest(path, fs, thresh, cycles, reverse=False): | |||
| print("波形活动时长: %.1f ms" % (meta['activity_duration'] * 1000)) | |||
| def plot_show(path, fs, thresh, ymax, cycles, reverse, save_path=None): | |||
| def local_linear_derivative(t_sec, values, window_s=5e-3, min_points=7): | |||
| """对非等间隔时间点做局部线性拟合,返回 d(values)/dt。 | |||
| 直接对相邻频率点差分会放大采样量化抖动;局部最小二乘斜率 | |||
| 使用真实时间间隔,并对这种抖动做平均。 | |||
| """ | |||
| t = np.asarray(t_sec, dtype=np.float64) | |||
| y = np.asarray(values, dtype=np.float64) | |||
| if t.ndim != 1 or y.ndim != 1 or len(t) != len(y): | |||
| raise ValueError("t_sec 和 values 必须是等长一维数组") | |||
| if len(t) < 2: | |||
| raise ValueError("至少需要两个点才能计算导数") | |||
| if window_s <= 0: | |||
| raise ValueError("导数拟合窗口必须大于0") | |||
| if np.any(np.diff(t) <= 0): | |||
| raise ValueError("时间点必须严格递增") | |||
| n = len(t) | |||
| min_points = min(n, max(2, int(min_points))) | |||
| half_window = window_s / 2.0 | |||
| left = np.searchsorted(t, t - half_window, side='left') | |||
| right = np.searchsorted(t, t + half_window, side='right') | |||
| # 低频段在固定时间窗口内可能点数太少,至少补足 min_points 个点。 | |||
| idx = np.arange(n) | |||
| fallback_left = np.clip(idx - min_points // 2, 0, n - min_points) | |||
| fallback_right = fallback_left + min_points | |||
| too_few = (right - left) < min_points | |||
| left[too_few] = fallback_left[too_few] | |||
| right[too_few] = fallback_right[too_few] | |||
| # 移动时间原点减少长时采集时前缀和相减的精度损失。 | |||
| x = t - (t[0] + t[-1]) / 2.0 | |||
| sx = np.concatenate(([0.0], np.cumsum(x))) | |||
| sy = np.concatenate(([0.0], np.cumsum(y))) | |||
| sxx = np.concatenate(([0.0], np.cumsum(x * x))) | |||
| sxy = np.concatenate(([0.0], np.cumsum(x * y))) | |||
| count = (right - left).astype(np.float64) | |||
| sum_x = sx[right] - sx[left] | |||
| sum_y = sy[right] - sy[left] | |||
| sum_xx = sxx[right] - sxx[left] | |||
| sum_xy = sxy[right] - sxy[left] | |||
| denominator = count * sum_xx - sum_x * sum_x | |||
| numerator = count * sum_xy - sum_x * sum_y | |||
| derivative = np.empty(n, dtype=np.float64) | |||
| good = np.abs(denominator) > np.finfo(np.float64).eps | |||
| derivative[good] = numerator[good] / denominator[good] | |||
| derivative[~good] = np.gradient(y, t)[~good] | |||
| return derivative | |||
| def plot_show(path, fs, thresh, ymax, cycles, reverse, save_path=None, | |||
| draw_d1=False, draw_d2=False, d1_window_ms=5.0, | |||
| d2_window_ms=None): | |||
| t, freq, hi_w, meta = load_time_freq(path, fs, thresh, cycles, reverse) | |||
| import matplotlib.pyplot as plt | |||
| @@ -183,8 +246,8 @@ def plot_show(path, fs, thresh, ymax, cycles, reverse, save_path=None): | |||
| y_full = freq | |||
| ax.set_xlim(0.0, meta['activity_duration'] * 1000 * 1.02) | |||
| ax.set_ylim(0, ymax if ymax > 0 else freq.max() * 1.08) | |||
| ax.set_title("%s 时频曲线(%d 个测量点,%d 周期平均,活动时长 %.0f ms)" % ( | |||
| os.path.basename(path), meta['pulses'], meta['cycles'], | |||
| ax.set_title("%s 时频曲线(检测到脉冲 %d,频率测量点 %d,%d 周期平均,活动时长 %.0f ms)" % ( | |||
| os.path.basename(path), meta['detected_pulses'], meta['pulses'], meta['cycles'], | |||
| meta['activity_duration'] * 1000)) | |||
| ax.set_xlabel("时间 (ms)") | |||
| ax.set_ylabel("频率 (Hz)") | |||
| @@ -195,10 +258,53 @@ def plot_show(path, fs, thresh, ymax, cycles, reverse, save_path=None): | |||
| ax.grid(True, which='minor', alpha=0.15) | |||
| ax.minorticks_on() | |||
| fig_der = None | |||
| draw_d1 = draw_d1 and (len(freq) >= 2) | |||
| draw_d2 = draw_d2 and (len(freq) >= 3) | |||
| if draw_d1 or draw_d2: | |||
| f64 = freq.astype(np.float64) | |||
| if d2_window_ms is None: | |||
| d2_window_ms = d1_window_ms | |||
| d1_full = local_linear_derivative(t, f64, d1_window_ms * 1e-3) | |||
| d2_full = (local_linear_derivative(t, d1_full, d2_window_ms * 1e-3) | |||
| if draw_d2 else None) | |||
| plot_count = int(draw_d1) + int(draw_d2) | |||
| fig_der, axes_der = plt.subplots(plot_count, 1, figsize=(15, 4.5 * plot_count), | |||
| sharex=True, squeeze=False) | |||
| fig_der.subplots_adjust(bottom=0.14, top=0.90) | |||
| row = 0 | |||
| if draw_d1: | |||
| ax_der = axes_der[row, 0] | |||
| ax_der.plot(x_full, d1_full, '-', lw=0.9, color='red', label='df/dt') | |||
| ax_der.set_ylabel("一阶导数 (Hz/s)") | |||
| ax_der.legend(loc='upper right') | |||
| row += 1 | |||
| if draw_d2: | |||
| ax_der = axes_der[row, 0] | |||
| ax_der.plot(x_full, d2_full, '-', lw=0.9, color='black', label='d²f/dt²') | |||
| ax_der.set_ylabel("二阶导数 (Hz/s²)") | |||
| ax_der.legend(loc='upper right') | |||
| for ax_der in axes_der[:, 0]: | |||
| ax_der.set_xlim(0.0, meta['activity_duration'] * 1000 * 1.02) | |||
| ax_der.grid(True, which='major', alpha=0.35) | |||
| ax_der.minorticks_on() | |||
| axes_der[-1, 0].set_xlabel("时间 (ms)") | |||
| axes_der[0, 0].set_title( | |||
| "时频曲线导数(一阶窗口 %.3g ms / 二阶窗口 %.3g ms)" % | |||
| (d1_window_ms, d2_window_ms)) | |||
| if save_path: | |||
| scatter.set_data(x_full, y_full) | |||
| root, ext = os.path.splitext(save_path) | |||
| fig.savefig(save_path, dpi=130) | |||
| print("已保存: %s" % save_path) | |||
| if fig_der is not None: | |||
| der_path = root + "_d" + ext | |||
| fig_der.savefig(der_path, dpi=130) | |||
| print("已保存: %s" % der_path) | |||
| plt.close(fig) | |||
| if fig_der is not None: | |||
| plt.close(fig_der) | |||
| return | |||
| # 交互:滚轮缩放 X(Ctrl+滚轮缩放 Y)/ 左键双向拖拽平移 / 双击复位 / 悬停高亮 | |||
| @@ -323,8 +429,9 @@ def plot_show(path, fs, thresh, ymax, cycles, reverse, save_path=None): | |||
| fig.canvas.mpl_connect('button_press_event', on_double) | |||
| print("打开窗口:滚轮缩放X / Ctrl+滚轮缩放Y / 左键双向拖拽平移 / 双击复位") | |||
| print("测量点 %d 个,使用 %d 周期平均,活动时长 %.1f ms" % ( | |||
| meta['pulses'], meta['cycles'], meta['activity_duration'] * 1000)) | |||
| print("检测到脉冲 %d,频率测量点 %d,使用 %d 周期平均,活动时长 %.1f ms" % ( | |||
| meta['detected_pulses'], meta['pulses'], meta['cycles'], | |||
| meta['activity_duration'] * 1000)) | |||
| plt.show() | |||
| @@ -344,6 +451,11 @@ def main(): | |||
| reverse = '--reverse' in opts | |||
| ymax = float(opts.get('--ymax', 0)) | |||
| save_path = opts.get('--save', '') | |||
| draw_d1 = '--d1' in opts | |||
| draw_d2 = '--d2' in opts | |||
| derivative_window_ms = float(opts.get('--dwindow-ms', 5.0)) | |||
| d1_window_ms = float(opts.get('--d1-window-ms', derivative_window_ms)) | |||
| d2_window_ms = float(opts.get('--d2-window-ms', derivative_window_ms)) | |||
| if not os.path.isfile(path): | |||
| print("错误:文件不存在 - %s" % path) | |||
| @@ -352,7 +464,8 @@ def main(): | |||
| if '--selftest' in opts: | |||
| selftest(path, fs, thresh, cycles, reverse) | |||
| else: | |||
| plot_show(path, fs, thresh, ymax, cycles, reverse, save_path or None) | |||
| plot_show(path, fs, thresh, ymax, cycles, reverse, save_path or None, | |||
| draw_d1, draw_d2, d1_window_ms, d2_window_ms) | |||
| if __name__ == '__main__': | |||
| @@ -4,24 +4,38 @@ | |||
| 数据格式: 逻辑分析仪导出的单通道数字采样,每字节 1 个采样点; | |||
| 电平 >= 阈值(默认128) 判为高(脉冲),否则为低。 | |||
| --reverse 时先把高低电平对调,再按同样规则找脉冲。 | |||
| 频率定义: 每脉冲频率 = 采样率 / 脉冲周期; | |||
| 周期 = 本脉冲高电平起点 -> 下一脉冲高电平起点; | |||
| 最后一个脉冲无下一脉冲,按高电平宽度 x2 近似(50% 占空比)。 | |||
| 仅使用实际检测到的相邻上升沿,不猜测末脉冲周期。 | |||
| 时间定义: 脉冲时间 = 高电平中点(与低电平/空闲段无关)。 | |||
| 用法: | |||
| python bin_to_time_freq.py <bin文件> [采样率Hz] [选项] | |||
| python bin_to_time_freq1.py <bin文件> [采样率Hz] [选项] | |||
| 示例: | |||
| python bin_to_time_freq.py "Document/PLSR_document/波形/10段.bin" 6250000 | |||
| python bin_to_time_freq.py xxx.bin 6250000 --ymax=12000 | |||
| python bin_to_time_freq.py xxx.bin 6250000 --save=out.png | |||
| python bin_to_time_freq.py xxx.bin 6250000 --selftest | |||
| python bin_to_time_freq1.py "Document/PLSR_document/波形/10段.bin" 6250000 | |||
| python bin_to_time_freq1.py xxx.bin 6250000 --ymax=12000 | |||
| python bin_to_time_freq1.py xxx.bin 6250000 --line | |||
| python bin_to_time_freq1.py xxx.bin 6250000 --reverse | |||
| python bin_to_time_freq1.py xxx.bin 6250000 --d1 --d2 | |||
| python bin_to_time_freq1.py xxx.bin 6250000 --d1 --dwindow-ms=10 | |||
| python bin_to_time_freq1.py xxx.bin 6250000 --d1 --d2 --d1-window-ms=5 --d2-window-ms=15 | |||
| python bin_to_time_freq1.py xxx.bin 6250000 --save=out.png | |||
| python bin_to_time_freq1.py xxx.bin 6250000 --selftest | |||
| 选项: | |||
| --thresh=128 电平阈值(默认128) | |||
| --ymax=12000 频率轴上限(默认自适应) | |||
| --line 将脉冲点连成折线(默认只画散点) | |||
| --reverse 高低电平对调后再算频率点(低电平当脉冲) | |||
| --d1 另开一张图:频率对时间的一阶导数 df/dt(红) | |||
| --d2 另开一张图:频率对时间的二阶导数 d²f/dt²(黑) | |||
| --dwindow-ms=5 一、二阶导数的公共拟合窗口,单位 ms(默认5) | |||
| --d1-window-ms 原函数 -> 一阶导数的拟合窗口(默认继承 --dwindow-ms) | |||
| --d2-window-ms 一阶导数 -> 二阶导数的拟合窗口(默认继承 --dwindow-ms) | |||
| --save=路径 保存 PNG 后退出(不弹窗) | |||
| --selftest 仅打印统计,不画图 | |||
| --help, -h 显示这份中文帮助后退出 | |||
| 交互(弹窗模式): | |||
| 滚轮 缩放 X 轴(向上放大/向下缩小,以鼠标位置为中心) | |||
| @@ -46,13 +60,20 @@ except Exception: | |||
| pass | |||
| def load_time_freq(path, fs, threshold=128): | |||
| def load_time_freq(path, fs, threshold=128, reverse=False): | |||
| """读取 bin,返回 (t_sec, freq_hz, hi_width_sec, meta)。 | |||
| t_sec 以第一个脉冲为 0 时刻;hi_width 为每脉冲高电平宽度。""" | |||
| t_sec 以第一个脉冲为 0 时刻;hi_width 为每脉冲高电平宽度。 | |||
| reverse=True 时先把高低电平对调,再按高电平找脉冲。""" | |||
| data = np.fromfile(path, dtype=np.uint8) | |||
| if data.size == 0: | |||
| raise ValueError("文件为空: %s" % path) | |||
| if fs <= 0: | |||
| raise ValueError("采样率必须大于0") | |||
| if not 0 <= threshold <= 255: | |||
| raise ValueError("阈值必须在0到255之间") | |||
| samples = (data >= threshold).astype(np.int8) | |||
| if reverse: | |||
| samples = 1 - samples | |||
| # run 级压缩 | |||
| changes = np.flatnonzero(np.diff(samples) != 0) + 1 | |||
| @@ -60,68 +81,132 @@ def load_time_freq(path, fs, threshold=128): | |||
| ends = np.concatenate((changes, [len(samples)])) | |||
| runs = np.column_stack((starts, ends, samples[starts])) | |||
| # 脉冲 = 高电平 run,且其后紧跟低电平 run | |||
| # 每个高电平 run 的起点都是一个上升沿。如果采集从高电平开始, | |||
| # 第一个 run 的真实上升沿在文件外,不能用来测周期。 | |||
| hi = np.flatnonzero(runs[:, 2] == 1) | |||
| hi = hi[hi + 1 < len(runs)] | |||
| lo_ok = runs[hi + 1, 2] == 0 | |||
| hi = hi[lo_ok] | |||
| if hi.size and runs[hi[0], 0] == 0: | |||
| hi = hi[1:] | |||
| if hi.size < 2: | |||
| raise ValueError("至少需要两个完整的上升沿才能计算频率: %s" % path) | |||
| t_start = runs[hi, 0].astype(np.int64) | |||
| hi_width = (runs[hi, 1] - runs[hi, 0]).astype(np.int64) | |||
| # 周期:高到高;末脉冲按 2x 高电平宽度近似 | |||
| next_start = np.append(t_start[1:], [t_start[-1] + 2 * hi_width[-1]]) | |||
| period = next_start - t_start | |||
| freq = fs / np.maximum(period, 1) | |||
| # 只用相邻实测上升沿求周期,不根据占空比猜测末脉冲频率。 | |||
| period = np.diff(t_start) | |||
| freq = float(fs) / np.maximum(period, 1) | |||
| # 时间:高电平中点,去起始偏移 | |||
| t_sec = (t_start + hi_width / 2.0) / fs | |||
| t_sec = (t_start[:-1] + hi_width[:-1] / 2.0) / fs | |||
| t_sec = t_sec - t_sec[0] | |||
| meta = { | |||
| 'total_samples': int(len(samples)), | |||
| 'duration': len(samples) / fs, | |||
| 'pulses': int(len(freq)), | |||
| 'detected_pulses': int(len(t_start)), | |||
| 'offset_ms': t_start[0] / fs * 1000, | |||
| } | |||
| return t_sec, freq, hi_width / fs, meta | |||
| def selftest(path, fs, thresh): | |||
| return t_sec, freq, hi_width[:-1] / fs, meta | |||
| def local_linear_derivative(t_sec, values, window_s=5e-3, min_points=7): | |||
| """对非等间隔时间点做局部线性拟合,返回 d(values)/dt。 | |||
| 直接对相邻单周期频率做差分会放大整数采样点带来的量化抖动; | |||
| 局部最小二乘斜率使用真实时间间隔,并对这种抖动做平均。 | |||
| """ | |||
| t = np.asarray(t_sec, dtype=np.float64) | |||
| y = np.asarray(values, dtype=np.float64) | |||
| if t.ndim != 1 or y.ndim != 1 or len(t) != len(y): | |||
| raise ValueError("t_sec 和 values 必须是等长一维数组") | |||
| if len(t) < 2: | |||
| raise ValueError("至少需要两个点才能计算导数") | |||
| if window_s <= 0: | |||
| raise ValueError("导数拟合窗口必须大于0") | |||
| if np.any(np.diff(t) <= 0): | |||
| raise ValueError("时间点必须严格递增") | |||
| n = len(t) | |||
| min_points = min(n, max(2, int(min_points))) | |||
| half_window = window_s / 2.0 | |||
| left = np.searchsorted(t, t - half_window, side='left') | |||
| right = np.searchsorted(t, t + half_window, side='right') | |||
| # 低频段在固定时间窗口内可能点数太少,至少补足 min_points 个点。 | |||
| idx = np.arange(n) | |||
| fallback_left = np.clip(idx - min_points // 2, 0, n - min_points) | |||
| fallback_right = fallback_left + min_points | |||
| too_few = (right - left) < min_points | |||
| left[too_few] = fallback_left[too_few] | |||
| right[too_few] = fallback_right[too_few] | |||
| # 前缀和使每个窗口的最小二乘斜率可以 O(1) 计算。 | |||
| # 先把时间原点移到数据中心,降低长时采集时前缀和相减的精度损失。 | |||
| x = t - (t[0] + t[-1]) / 2.0 | |||
| sx = np.concatenate(([0.0], np.cumsum(x))) | |||
| sy = np.concatenate(([0.0], np.cumsum(y))) | |||
| sxx = np.concatenate(([0.0], np.cumsum(x * x))) | |||
| sxy = np.concatenate(([0.0], np.cumsum(x * y))) | |||
| count = (right - left).astype(np.float64) | |||
| sum_x = sx[right] - sx[left] | |||
| sum_y = sy[right] - sy[left] | |||
| sum_xx = sxx[right] - sxx[left] | |||
| sum_xy = sxy[right] - sxy[left] | |||
| denominator = count * sum_xx - sum_x * sum_x | |||
| numerator = count * sum_xy - sum_x * sum_y | |||
| derivative = np.empty(n, dtype=np.float64) | |||
| good = np.abs(denominator) > np.finfo(np.float64).eps | |||
| derivative[good] = numerator[good] / denominator[good] | |||
| derivative[~good] = np.gradient(y, t)[~good] | |||
| return derivative | |||
| def selftest(path, fs, thresh, reverse=False): | |||
| import statistics | |||
| t, freq, hi_w, meta = load_time_freq(path, fs, thresh) | |||
| t, freq, hi_w, meta = load_time_freq(path, fs, thresh, reverse) | |||
| print("文件: %s" % path) | |||
| print("总采样: %d (%.3f s @ %.2f MS/s)" % (meta['total_samples'], meta['duration'], fs / 1e6)) | |||
| print("起始采集偏移: %.1f ms" % meta['offset_ms']) | |||
| print("脉冲总数: %d" % meta['pulses']) | |||
| print("检测到脉冲: %d,频率测量点: %d" % ( | |||
| meta['detected_pulses'], meta['pulses'])) | |||
| if meta['pulses']: | |||
| print("频率 min=%.0f max=%.0f 中位=%.0f Hz" % ( | |||
| freq.min(), freq.max(), statistics.median(freq))) | |||
| print("末脉冲: t=%.3f ms, 高电平 %.3f ms, %.0f Hz" % ( | |||
| print("末测量点: t=%.3f ms, 高电平 %.3f ms, %.0f Hz" % ( | |||
| t[-1] * 1000, hi_w[-1] * 1000, freq[-1])) | |||
| print("波形活动时长: %.1f ms" % ((t[-1] + hi_w[-1] / 2) * 1000)) | |||
| def plot_show(path, fs, thresh, ymax, save_path=None): | |||
| t, freq, hi_w, meta = load_time_freq(path, fs, thresh) | |||
| def plot_show(path, fs, thresh, ymax, save_path=None, draw_line=False, | |||
| reverse=False, draw_d1=False, draw_d2=False, | |||
| d1_window_ms=5.0, d2_window_ms=None): | |||
| t, freq, hi_w, meta = load_time_freq(path, fs, thresh, reverse) | |||
| import matplotlib.pyplot as plt | |||
| from matplotlib.ticker import MaxNLocator | |||
| draw_d1 = draw_d1 and (len(freq) >= 2) | |||
| draw_d2 = draw_d2 and (len(freq) >= 3) | |||
| fig, ax = plt.subplots(figsize=(15, 7)) | |||
| fig.subplots_adjust(bottom=0.10, top=0.92) | |||
| # 全脉冲散点:复用 artist,重绘时按可见范围抽稀(大文件流畅) | |||
| MAX_VISIBLE_POINTS = 5000 # 可见范围内最多绘制的点数,超过则等间隔抽稀 | |||
| (scatter,) = ax.plot([], [], '.', ms=1.5, color='C0', alpha=0.5, zorder=1) | |||
| (scatter,) = ax.plot([], [], '.', ms=1.5, color='C0', alpha=0.5, zorder=2) | |||
| line = None | |||
| if draw_line: | |||
| (line,) = ax.plot([], [], '-', lw=0.9, color='C0', alpha=0.85, 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_ylim(0, ymax if ymax > 0 else freq.max() * 1.08) | |||
| ax.set_title("%s 时频曲线(%d 脉冲,活动时长 %.0f ms)" % ( | |||
| os.path.basename(path), meta['pulses'], | |||
| (t[-1] + hi_w[-1] / 2) * 1000)) | |||
| title_extra = ",高低对调" if reverse else "" | |||
| ax.set_title("%s 时频曲线(检测到脉冲 %d,频率测量点 %d,活动时长 %.0f ms%s)" % ( | |||
| os.path.basename(path), meta['detected_pulses'], meta['pulses'], | |||
| (t[-1] + hi_w[-1] / 2) * 1000, title_extra)) | |||
| ax.set_xlabel("时间 (ms)") | |||
| ax.set_ylabel("频率 (Hz)") | |||
| # 更密的刻度 | |||
| @@ -131,10 +216,53 @@ def plot_show(path, fs, thresh, ymax, save_path=None): | |||
| ax.grid(True, which='minor', alpha=0.15) | |||
| ax.minorticks_on() | |||
| fig_der = None | |||
| if draw_d1 or draw_d2: | |||
| f64 = freq.astype(np.float64) | |||
| if d2_window_ms is None: | |||
| d2_window_ms = d1_window_ms | |||
| d1_full = local_linear_derivative(t, f64, d1_window_ms * 1e-3) | |||
| d2_full = (local_linear_derivative(t, d1_full, d2_window_ms * 1e-3) | |||
| if draw_d2 else None) | |||
| plot_count = int(draw_d1) + int(draw_d2) | |||
| fig_der, axes_der = plt.subplots(plot_count, 1, figsize=(15, 4.5 * plot_count), | |||
| sharex=True, squeeze=False) | |||
| fig_der.subplots_adjust(bottom=0.14, top=0.90) | |||
| row = 0 | |||
| if draw_d1: | |||
| ax_der = axes_der[row, 0] | |||
| ax_der.plot(x_full, d1_full, '-', lw=0.9, color='red', label='df/dt') | |||
| ax_der.set_ylabel("一阶导数 (Hz/s)") | |||
| ax_der.legend(loc='upper right') | |||
| row += 1 | |||
| if draw_d2: | |||
| ax_der = axes_der[row, 0] | |||
| ax_der.plot(x_full, d2_full, '-', lw=0.9, color='black', label='d²f/dt²') | |||
| ax_der.set_ylabel("二阶导数 (Hz/s²)") | |||
| ax_der.legend(loc='upper right') | |||
| for ax_der in axes_der[:, 0]: | |||
| ax_der.set_xlim(0.0, (t[-1] + hi_w[-1]) * 1000 * 1.02) | |||
| ax_der.grid(True, which='major', alpha=0.35) | |||
| ax_der.minorticks_on() | |||
| axes_der[-1, 0].set_xlabel("时间 (ms)") | |||
| axes_der[0, 0].set_title( | |||
| "时频曲线导数(一阶窗口 %.3g ms / 二阶窗口 %.3g ms)" % | |||
| (d1_window_ms, d2_window_ms)) | |||
| if save_path: | |||
| scatter.set_data(x_full, y_full) | |||
| if line is not None: | |||
| line.set_data(x_full, y_full) | |||
| root, ext = os.path.splitext(save_path) | |||
| fig.savefig(save_path, dpi=130) | |||
| print("已保存: %s" % save_path) | |||
| if fig_der is not None: | |||
| der_path = root + "_d" + ext | |||
| fig_der.savefig(der_path, dpi=130) | |||
| print("已保存: %s" % der_path) | |||
| plt.close(fig) | |||
| if fig_der is not None: | |||
| plt.close(fig_der) | |||
| return | |||
| # 交互:滚轮缩放 X(Ctrl+滚轮缩放 Y)/ 左键双向拖拽平移 / 双击复位 / 悬停高亮 | |||
| @@ -161,6 +289,8 @@ def plot_show(path, fs, thresh, ymax, save_path=None): | |||
| else: | |||
| idx = np.flatnonzero(mask) | |||
| scatter.set_data(x_full[idx], y_full[idx]) | |||
| if line is not None: | |||
| line.set_data(x_full[idx], y_full[idx]) | |||
| def on_scroll(event): | |||
| if event.inaxes is not ax or event.xdata is None: | |||
| @@ -259,8 +389,9 @@ def plot_show(path, fs, thresh, ymax, save_path=None): | |||
| fig.canvas.mpl_connect('button_press_event', on_double) | |||
| print("打开窗口:滚轮缩放X / Ctrl+滚轮缩放Y / 左键双向拖拽平移 / 双击复位") | |||
| print("脉冲 %d 个,活动时长 %.1f ms" % ( | |||
| meta['pulses'], (t[-1] + hi_w[-1] / 2) * 1000)) | |||
| print("检测到脉冲 %d,频率测量点 %d,活动时长 %.1f ms" % ( | |||
| meta['detected_pulses'], meta['pulses'], | |||
| (t[-1] + hi_w[-1] / 2) * 1000)) | |||
| plt.show() | |||
| @@ -269,7 +400,7 @@ def main(): | |||
| opts = {a.split('=', 1)[0]: (a.split('=', 1)[1] if '=' in a else True) | |||
| for a in sys.argv[1:] if a.startswith('--')} | |||
| if len(args) < 1 or '--help' in opts or '-h' in opts: | |||
| if len(args) < 1 or '--help' in opts or '-h' in sys.argv[1:]: | |||
| print(__doc__) | |||
| sys.exit(0) | |||
| @@ -278,15 +409,23 @@ def main(): | |||
| thresh = int(opts.get('--thresh', 128)) | |||
| ymax = float(opts.get('--ymax', 0)) | |||
| save_path = opts.get('--save', '') | |||
| draw_line = '--line' in opts | |||
| reverse = '--reverse' in opts | |||
| draw_d1 = '--d1' in opts | |||
| draw_d2 = '--d2' in opts | |||
| derivative_window_ms = float(opts.get('--dwindow-ms', 5.0)) | |||
| d1_window_ms = float(opts.get('--d1-window-ms', derivative_window_ms)) | |||
| d2_window_ms = float(opts.get('--d2-window-ms', derivative_window_ms)) | |||
| if not os.path.isfile(path): | |||
| print("错误:文件不存在 - %s" % path) | |||
| sys.exit(1) | |||
| if '--selftest' in opts: | |||
| selftest(path, fs, thresh) | |||
| selftest(path, fs, thresh, reverse) | |||
| else: | |||
| plot_show(path, fs, thresh, ymax, save_path or None) | |||
| plot_show(path, fs, thresh, ymax, save_path or None, draw_line, | |||
| reverse, draw_d1, draw_d2, d1_window_ms, d2_window_ms) | |||
| if __name__ == '__main__': | |||
| @@ -63,34 +63,150 @@ void PlsrPlannerTimingReset(void) | |||
| } | |||
| #endif | |||
| static const uint32_t PlsrPlannerSmoothIntegralQ24[65] = | |||
| #define PLSR_PLANNER_CURVE_TABLE_BITS (9U) | |||
| #define PLSR_PLANNER_CURVE_TABLE_INTERVALS (1UL << PLSR_PLANNER_CURVE_TABLE_BITS) | |||
| #define PLSR_PLANNER_CURVE_TABLE_SIZE (PLSR_PLANNER_CURVE_TABLE_INTERVALS + 1UL) | |||
| #define PLSR_PLANNER_CURVE_DERIVATIVE_SHIFT (8U + PLSR_PLANNER_CURVE_TABLE_BITS) | |||
| /* curveMode 1: fixed seven-section jerk profile. Each entry/exit ramp | |||
| uses a 1:2:1 constant-jerk/constant-acceleration/constant-jerk ratio. | |||
| The table stores the integral of the normalized frequency blend. */ | |||
| static const uint32_t PlsrPlannerSmoothIntegralQ24[PLSR_PLANNER_CURVE_TABLE_SIZE] = | |||
| { | |||
| 0UL, 64UL, 504UL, 1688UL, 3968UL, 7688UL, 13176UL, 20752UL, | |||
| 30720UL, 43376UL, 59000UL, 77864UL, 100224UL, 126328UL, 156408UL, | |||
| 190688UL, 229376UL, 272672UL, 320760UL, 373816UL, 432000UL, | |||
| 495464UL, 564344UL, 638768UL, 718848UL, 804688UL, 896376UL, | |||
| 993992UL, 1097600UL, 1207256UL, 1323000UL, 1444864UL, 1572864UL, | |||
| 1707008UL, 1847288UL, 1993688UL, 2146176UL, 2304712UL, 2469240UL, | |||
| 2639696UL, 2816000UL, 2998064UL, 3185784UL, 3379048UL, 3577728UL, | |||
| 3781688UL, 3990776UL, 4204832UL, 4423680UL, 4647136UL, 4875000UL, | |||
| 5107064UL, 5343104UL, 5582888UL, 5826168UL, 6072688UL, 6322176UL, | |||
| 6574352UL, 6828920UL, 7085576UL, 7344000UL, 7603864UL, 7864824UL, | |||
| 8126528UL, 8388608UL | |||
| 0UL, 0UL, 1UL, 3UL, 7UL, 14UL, 24UL, 38UL, | |||
| 57UL, 81UL, 111UL, 148UL, 192UL, 244UL, 305UL, 375UL, | |||
| 455UL, 546UL, 648UL, 762UL, 889UL, 1029UL, 1183UL, 1352UL, | |||
| 1536UL, 1736UL, 1953UL, 2187UL, 2439UL, 2710UL, 3000UL, 3310UL, | |||
| 3641UL, 3993UL, 4367UL, 4764UL, 5184UL, 5628UL, 6097UL, 6591UL, | |||
| 7111UL, 7658UL, 8232UL, 8834UL, 9465UL, 10125UL, 10815UL, 11536UL, | |||
| 12288UL, 13072UL, 13889UL, 14739UL, 15623UL, 16542UL, 17496UL, 18486UL, | |||
| 19513UL, 20577UL, 21679UL, 22820UL, 24000UL, 25220UL, 26481UL, 27783UL, | |||
| 29127UL, 30514UL, 31944UL, 33418UL, 34937UL, 36501UL, 38111UL, 39768UL, | |||
| 41472UL, 43224UL, 45025UL, 46875UL, 48775UL, 50726UL, 52728UL, 54782UL, | |||
| 56889UL, 59049UL, 61263UL, 63532UL, 65856UL, 68236UL, 70673UL, 73167UL, | |||
| 75719UL, 78330UL, 81000UL, 83730UL, 86521UL, 89373UL, 92287UL, 95264UL, | |||
| 98304UL, 101408UL, 104577UL, 107811UL, 111111UL, 114478UL, 117912UL, 121414UL, | |||
| 124985UL, 128625UL, 132335UL, 136116UL, 139968UL, 143892UL, 147889UL, 151959UL, | |||
| 156103UL, 160322UL, 164616UL, 168986UL, 173433UL, 177957UL, 182559UL, 187240UL, | |||
| 192000UL, 196840UL, 201761UL, 206763UL, 211847UL, 217014UL, 222264UL, 227598UL, | |||
| 233017UL, 238521UL, 244110UL, 249785UL, 255545UL, 261390UL, 267321UL, 273337UL, | |||
| 279438UL, 285625UL, 291897UL, 298254UL, 304697UL, 311225UL, 317838UL, 324537UL, | |||
| 331321UL, 338190UL, 345145UL, 352185UL, 359310UL, 366521UL, 373817UL, 381198UL, | |||
| 388665UL, 396217UL, 403854UL, 411577UL, 419385UL, 427278UL, 435257UL, 443321UL, | |||
| 451470UL, 459705UL, 468025UL, 476430UL, 484921UL, 493497UL, 502158UL, 510905UL, | |||
| 519737UL, 528654UL, 537657UL, 546745UL, 555918UL, 565177UL, 574521UL, 583950UL, | |||
| 593465UL, 603065UL, 612750UL, 622521UL, 632377UL, 642318UL, 652345UL, 662457UL, | |||
| 672654UL, 682937UL, 693305UL, 703758UL, 714297UL, 724921UL, 735630UL, 746425UL, | |||
| 757305UL, 768270UL, 779321UL, 790457UL, 801678UL, 812985UL, 824377UL, 835854UL, | |||
| 847417UL, 859065UL, 870798UL, 882617UL, 894521UL, 906510UL, 918585UL, 930745UL, | |||
| 942990UL, 955321UL, 967737UL, 980238UL, 992825UL, 1005497UL, 1018254UL, 1031097UL, | |||
| 1044025UL, 1057038UL, 1070137UL, 1083321UL, 1096590UL, 1109945UL, 1123385UL, 1136910UL, | |||
| 1150521UL, 1164217UL, 1177998UL, 1191865UL, 1205817UL, 1219854UL, 1233977UL, 1248185UL, | |||
| 1262478UL, 1276857UL, 1291321UL, 1305870UL, 1320505UL, 1335225UL, 1350030UL, 1364921UL, | |||
| 1379897UL, 1394958UL, 1410105UL, 1425337UL, 1440654UL, 1456057UL, 1471545UL, 1487118UL, | |||
| 1502777UL, 1518521UL, 1534350UL, 1550265UL, 1566265UL, 1582350UL, 1598521UL, 1614777UL, | |||
| 1631118UL, 1647545UL, 1664057UL, 1680654UL, 1697337UL, 1714105UL, 1730958UL, 1747897UL, | |||
| 1764921UL, 1782030UL, 1799225UL, 1816505UL, 1833870UL, 1851321UL, 1868857UL, 1886478UL, | |||
| 1904185UL, 1921977UL, 1939854UL, 1957817UL, 1975865UL, 1993998UL, 2012217UL, 2030521UL, | |||
| 2048910UL, 2067385UL, 2085945UL, 2104590UL, 2123321UL, 2142137UL, 2161038UL, 2180025UL, | |||
| 2199097UL, 2218254UL, 2237497UL, 2256825UL, 2276238UL, 2295737UL, 2315321UL, 2334990UL, | |||
| 2354745UL, 2374585UL, 2394510UL, 2414521UL, 2434617UL, 2454798UL, 2475065UL, 2495417UL, | |||
| 2515854UL, 2536377UL, 2556985UL, 2577678UL, 2598457UL, 2619321UL, 2640270UL, 2661305UL, | |||
| 2682425UL, 2703630UL, 2724921UL, 2746297UL, 2767758UL, 2789305UL, 2810937UL, 2832654UL, | |||
| 2854457UL, 2876345UL, 2898318UL, 2920377UL, 2942521UL, 2964750UL, 2987065UL, 3009465UL, | |||
| 3031950UL, 3054521UL, 3077177UL, 3099918UL, 3122745UL, 3145657UL, 3168654UL, 3191737UL, | |||
| 3214905UL, 3238158UL, 3261497UL, 3284921UL, 3308430UL, 3332025UL, 3355705UL, 3379470UL, | |||
| 3403321UL, 3427257UL, 3451278UL, 3475385UL, 3499577UL, 3523854UL, 3548217UL, 3572665UL, | |||
| 3597198UL, 3621817UL, 3646521UL, 3671310UL, 3696185UL, 3721145UL, 3746190UL, 3771321UL, | |||
| 3796537UL, 3821838UL, 3847225UL, 3872697UL, 3898254UL, 3923897UL, 3949625UL, 3975438UL, | |||
| 4001337UL, 4027321UL, 4053390UL, 4079545UL, 4105785UL, 4132110UL, 4158521UL, 4185017UL, | |||
| 4211598UL, 4238265UL, 4265017UL, 4291854UL, 4318777UL, 4345785UL, 4372878UL, 4400057UL, | |||
| 4427321UL, 4454670UL, 4482104UL, 4509622UL, 4537223UL, 4564907UL, 4592673UL, 4620520UL, | |||
| 4648448UL, 4676456UL, 4704543UL, 4732709UL, 4760953UL, 4789274UL, 4817672UL, 4846146UL, | |||
| 4874695UL, 4903319UL, 4932017UL, 4960788UL, 4989632UL, 5018548UL, 5047535UL, 5076593UL, | |||
| 5105721UL, 5134918UL, 5164184UL, 5193518UL, 5222919UL, 5252387UL, 5281921UL, 5311520UL, | |||
| 5341184UL, 5370912UL, 5400703UL, 5430557UL, 5460473UL, 5490450UL, 5520488UL, 5550586UL, | |||
| 5580743UL, 5610959UL, 5641233UL, 5671564UL, 5701952UL, 5732396UL, 5762895UL, 5793449UL, | |||
| 5824057UL, 5854718UL, 5885432UL, 5916198UL, 5947015UL, 5977883UL, 6008801UL, 6039768UL, | |||
| 6070784UL, 6101848UL, 6132959UL, 6164117UL, 6195321UL, 6226570UL, 6257864UL, 6289202UL, | |||
| 6320583UL, 6352007UL, 6383473UL, 6414980UL, 6446528UL, 6478116UL, 6509743UL, 6541409UL, | |||
| 6573113UL, 6604854UL, 6636632UL, 6668446UL, 6700295UL, 6732179UL, 6764097UL, 6796048UL, | |||
| 6828032UL, 6860048UL, 6892095UL, 6924173UL, 6956281UL, 6988418UL, 7020584UL, 7052778UL, | |||
| 7084999UL, 7117247UL, 7149521UL, 7181820UL, 7214144UL, 7246492UL, 7278863UL, 7311257UL, | |||
| 7343673UL, 7376110UL, 7408568UL, 7441046UL, 7473543UL, 7506059UL, 7538593UL, 7571144UL, | |||
| 7603712UL, 7636296UL, 7668895UL, 7701509UL, 7734137UL, 7766778UL, 7799432UL, 7832098UL, | |||
| 7864775UL, 7897463UL, 7930161UL, 7962868UL, 7995584UL, 8028308UL, 8061039UL, 8093777UL, | |||
| 8126521UL, 8159270UL, 8192024UL, 8224782UL, 8257543UL, 8290307UL, 8323073UL, 8355840UL, | |||
| 8388608UL | |||
| }; | |||
| static const uint32_t PlsrPlannerSineIntegralQ24[65] = | |||
| static const uint32_t PlsrPlannerSineIntegralQ24[PLSR_PLANNER_CURVE_TABLE_SIZE] = | |||
| { | |||
| 0UL, 53UL, 421UL, 1420UL, 3362UL, 6560UL, 11321UL, 17949UL, | |||
| 26744UL, 38000UL, 52007UL, 69047UL, 89393UL, 113314UL, 141066UL, | |||
| 172899UL, 209052UL, 249753UL, 295221UL, 345662UL, 401269UL, | |||
| 462225UL, 528698UL, 600845UL, 678806UL, 762711UL, 852672UL, | |||
| 948789UL, 1051146UL, 1159812UL, 1274841UL, 1396271UL, 1524127UL, | |||
| 1658415UL, 1799129UL, 1946244UL, 2099722UL, 2259509UL, 2425536UL, | |||
| 2597719UL, 2775958UL, 2960141UL, 3150138UL, 3345809UL, 3546997UL, | |||
| 3753534UL, 3965237UL, 4181913UL, 4403356UL, 4629347UL, 4859658UL, | |||
| 5094050UL, 5332273UL, 5574071UL, 5819175UL, 6067312UL, 6318200UL, | |||
| 6571549UL, 6827065UL, 7084448UL, 7343394UL, 7603596UL, 7864741UL, | |||
| 8126517UL, 8388608UL | |||
| 0UL, 0UL, 1UL, 3UL, 7UL, 13UL, 22UL, 35UL, | |||
| 53UL, 75UL, 103UL, 137UL, 178UL, 226UL, 282UL, 347UL, | |||
| 421UL, 505UL, 599UL, 705UL, 822UL, 951UL, 1094UL, 1250UL, | |||
| 1420UL, 1604UL, 1805UL, 2021UL, 2254UL, 2503UL, 2771UL, 3057UL, | |||
| 3362UL, 3687UL, 4032UL, 4398UL, 4785UL, 5194UL, 5626UL, 6081UL, | |||
| 6560UL, 7063UL, 7592UL, 8146UL, 8726UL, 9333UL, 9967UL, 10630UL, | |||
| 11321UL, 12041UL, 12791UL, 13571UL, 14382UL, 15225UL, 16100UL, 17008UL, | |||
| 17949UL, 18923UL, 19933UL, 20977UL, 22057UL, 23173UL, 24325UL, 25516UL, | |||
| 26744UL, 28010UL, 29316UL, 30661UL, 32046UL, 33472UL, 34939UL, 36449UL, | |||
| 38000UL, 39595UL, 41233UL, 42915UL, 44642UL, 46414UL, 48232UL, 50096UL, | |||
| 52007UL, 53966UL, 55972UL, 58027UL, 60131UL, 62284UL, 64487UL, 66742UL, | |||
| 69047UL, 71404UL, 73813UL, 76275UL, 78790UL, 81359UL, 83982UL, 86660UL, | |||
| 89393UL, 92182UL, 95028UL, 97930UL, 100890UL, 103908UL, 106984UL, 110119UL, | |||
| 113314UL, 116568UL, 119882UL, 123258UL, 126695UL, 130194UL, 133755UL, 137379UL, | |||
| 141066UL, 144817UL, 148632UL, 152512UL, 156457UL, 160468UL, 164545UL, 168688UL, | |||
| 172899UL, 177177UL, 181523UL, 185937UL, 190421UL, 194973UL, 199596UL, 204289UL, | |||
| 209052UL, 213886UL, 218792UL, 223770UL, 228820UL, 233943UL, 239140UL, 244409UL, | |||
| 249753UL, 255172UL, 260665UL, 266234UL, 271878UL, 277599UL, 283396UL, 289270UL, | |||
| 295221UL, 301250UL, 307358UL, 313543UL, 319808UL, 326151UL, 332575UL, 339078UL, | |||
| 345662UL, 352326UL, 359072UL, 365899UL, 372808UL, 379799UL, 386873UL, 394029UL, | |||
| 401269UL, 408592UL, 416000UL, 423491UL, 431068UL, 438729UL, 446475UL, 454307UL, | |||
| 462225UL, 470229UL, 478320UL, 486497UL, 494762UL, 503114UL, 511554UL, 520082UL, | |||
| 528698UL, 537403UL, 546197UL, 555080UL, 564053UL, 573116UL, 582268UL, 591511UL, | |||
| 600845UL, 610269UL, 619785UL, 629392UL, 639090UL, 648881UL, 658763UL, 668739UL, | |||
| 678806UL, 688967UL, 699221UL, 709568UL, 720008UL, 730543UL, 741171UL, 751894UL, | |||
| 762711UL, 773623UL, 784629UL, 795731UL, 806928UL, 818220UL, 829608UL, 841092UL, | |||
| 852672UL, 864348UL, 876121UL, 887990UL, 899955UL, 912018UL, 924178UL, 936435UL, | |||
| 948789UL, 961241UL, 973790UL, 986438UL, 999183UL, 1012026UL, 1024968UL, 1038007UL, | |||
| 1051146UL, 1064383UL, 1077718UL, 1091153UL, 1104686UL, 1118319UL, 1132051UL, 1145882UL, | |||
| 1159812UL, 1173841UL, 1187971UL, 1202200UL, 1216528UL, 1230956UL, 1245485UL, 1260113UL, | |||
| 1274841UL, 1289669UL, 1304597UL, 1319626UL, 1334754UL, 1349983UL, 1365312UL, 1380742UL, | |||
| 1396271UL, 1411902UL, 1427632UL, 1443464UL, 1459395UL, 1475428UL, 1491560UL, 1507793UL, | |||
| 1524127UL, 1540561UL, 1557096UL, 1573732UL, 1590467UL, 1607304UL, 1624240UL, 1641278UL, | |||
| 1658415UL, 1675654UL, 1692992UL, 1710431UL, 1727970UL, 1745610UL, 1763349UL, 1781189UL, | |||
| 1799129UL, 1817169UL, 1835309UL, 1853548UL, 1871888UL, 1890328UL, 1908867UL, 1927505UL, | |||
| 1946244UL, 1965082UL, 1984019UL, 2003055UL, 2022190UL, 2041425UL, 2060758UL, 2080191UL, | |||
| 2099722UL, 2119351UL, 2139080UL, 2158906UL, 2178831UL, 2198854UL, 2218974UL, 2239193UL, | |||
| 2259509UL, 2279923UL, 2300434UL, 2321042UL, 2341747UL, 2362550UL, 2383449UL, 2404444UL, | |||
| 2425536UL, 2446724UL, 2468008UL, 2489388UL, 2510864UL, 2532435UL, 2554101UL, 2575863UL, | |||
| 2597719UL, 2619670UL, 2641715UL, 2663855UL, 2686088UL, 2708416UL, 2730837UL, 2753351UL, | |||
| 2775958UL, 2798659UL, 2821451UL, 2844337UL, 2867314UL, 2890384UL, 2913545UL, 2936797UL, | |||
| 2960141UL, 2983575UL, 3007100UL, 3030716UL, 3054421UL, 3078216UL, 3102101UL, 3126075UL, | |||
| 3150138UL, 3174290UL, 3198530UL, 3222858UL, 3247274UL, 3271777UL, 3296368UL, 3321045UL, | |||
| 3345809UL, 3370659UL, 3395595UL, 3420617UL, 3445724UL, 3470915UL, 3496192UL, 3521552UL, | |||
| 3546997UL, 3572525UL, 3598137UL, 3623831UL, 3649608UL, 3675467UL, 3701408UL, 3727430UL, | |||
| 3753534UL, 3779718UL, 3805983UL, 3832327UL, 3858752UL, 3885255UL, 3911838UL, 3938498UL, | |||
| 3965237UL, 3992054UL, 4018948UL, 4045919UL, 4072966UL, 4100090UL, 4127289UL, 4154564UL, | |||
| 4181913UL, 4209337UL, 4236836UL, 4264407UL, 4292052UL, 4319770UL, 4347560UL, 4375422UL, | |||
| 4403356UL, 4431361UL, 4459436UL, 4487581UL, 4515797UL, 4544081UL, 4572435UL, 4600857UL, | |||
| 4629347UL, 4657904UL, 4686529UL, 4715220UL, 4743977UL, 4772800UL, 4801688UL, 4830641UL, | |||
| 4859658UL, 4888739UL, 4917883UL, 4947090UL, 4976359UL, 5005690UL, 5035082UL, 5064536UL, | |||
| 5094050UL, 5123623UL, 5153256UL, 5182948UL, 5212698UL, 5242506UL, 5272372UL, 5302294UL, | |||
| 5332273UL, 5362308UL, 5392398UL, 5422543UL, 5452742UL, 5482995UL, 5513301UL, 5543660UL, | |||
| 5574071UL, 5604534UL, 5635047UL, 5665612UL, 5696227UL, 5726891UL, 5757604UL, 5788366UL, | |||
| 5819175UL, 5850032UL, 5880936UL, 5911886UL, 5942882UL, 5973923UL, 6005009UL, 6036139UL, | |||
| 6067312UL, 6098529UL, 6129787UL, 6161088UL, 6192430UL, 6223813UL, 6255236UL, 6286698UL, | |||
| 6318200UL, 6349740UL, 6381317UL, 6412933UL, 6444585UL, 6476273UL, 6507997UL, 6539755UL, | |||
| 6571549UL, 6603376UL, 6635236UL, 6667129UL, 6699054UL, 6731011UL, 6762999UL, 6795017UL, | |||
| 6827065UL, 6859142UL, 6891247UL, 6923381UL, 6955542UL, 6987730UL, 7019944UL, 7052183UL, | |||
| 7084448UL, 7116737UL, 7149050UL, 7181386UL, 7213745UL, 7246126UL, 7278528UL, 7310951UL, | |||
| 7343394UL, 7375857UL, 7408339UL, 7440839UL, 7473358UL, 7505893UL, 7538445UL, 7571012UL, | |||
| 7603596UL, 7636194UL, 7668806UL, 7701431UL, 7734070UL, 7766721UL, 7799383UL, 7832057UL, | |||
| 7864741UL, 7897435UL, 7930138UL, 7962850UL, 7995570UL, 8028297UL, 8061031UL, 8093771UL, | |||
| 8126517UL, 8159267UL, 8192022UL, 8224781UL, 8257543UL, 8290307UL, 8323073UL, 8355840UL, | |||
| 8388608UL | |||
| }; | |||
| static uint32_t PlsrPlannerAbsDifference(uint32_t first, uint32_t second) | |||
| @@ -294,7 +410,7 @@ static uint64_t PlsrPlannerCurveIntegralQ32(uint64_t progressQ32, | |||
| } | |||
| table = (curveMode == 1U) ? PlsrPlannerSmoothIntegralQ24 | |||
| : PlsrPlannerSineIntegralQ24; | |||
| scaled = progressQ32 * 64ULL; | |||
| scaled = progressQ32 * PLSR_PLANNER_CURVE_TABLE_INTERVALS; | |||
| index = (uint32_t)(scaled >> 32U); | |||
| fraction = (uint32_t)scaled; | |||
| first = (uint64_t)table[index] << 8U; | |||
| @@ -365,10 +481,11 @@ static uint32_t PlsrPlannerInstantFrequency( | |||
| table = (context->block.curveMode == 1U) | |||
| ? PlsrPlannerSmoothIntegralQ24 | |||
| : PlsrPlannerSineIntegralQ24; | |||
| scaled = progressQ32 * 64ULL; | |||
| scaled = progressQ32 * PLSR_PLANNER_CURVE_TABLE_INTERVALS; | |||
| index = (uint32_t)(scaled >> 32U); | |||
| curveProgressQ32 = | |||
| (uint64_t)(table[index + 1UL] - table[index]) << 14U; | |||
| (uint64_t)(table[index + 1UL] - table[index]) | |||
| << PLSR_PLANNER_CURVE_DERIVATIVE_SHIFT; | |||
| } | |||
| if (context->rampToHz >= context->rampFromHz) | |||
| { | |||