Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 
 

724 строки
23 KiB

  1. #include "plsr_profile.h"
  2. #include <math.h>
  3. #include <string.h>
  4. /* 正弦表:256 项,sin(pi*i/256) 的 Q16 表示。 */
  5. static const uint16_t PlsrProfileSineTable[256] =
  6. {
  7. 0, 804, 1608, 2412, 3216, 4019, 4821, 5623,
  8. 6424, 7224, 8022, 8820, 9616, 10411, 11204, 11996,
  9. 12785, 13573, 14359, 15143, 15924, 16703, 17479, 18253,
  10. 19024, 19792, 20557, 21320, 22078, 22834, 23586, 24335,
  11. 25080, 25821, 26558, 27291, 28020, 28745, 29466, 30182,
  12. 30893, 31600, 32303, 33000, 33692, 34380, 35062, 35738,
  13. 36410, 37076, 37736, 38391, 39040, 39683, 40320, 40951,
  14. 41576, 42194, 42806, 43412, 44011, 44604, 45190, 45769,
  15. 46341, 46906, 47464, 48015, 48559, 49095, 49624, 50146,
  16. 50660, 51166, 51665, 52156, 52639, 53114, 53581, 54040,
  17. 54491, 54934, 55368, 55794, 56212, 56621, 57022, 57414,
  18. 57798, 58172, 58538, 58896, 59244, 59583, 59914, 60235,
  19. 60547, 60851, 61145, 61429, 61705, 61971, 62228, 62476,
  20. 62714, 62943, 63162, 63372, 63572, 63763, 63944, 64115,
  21. 64277, 64429, 64571, 64704, 64827, 64940, 65043, 65137,
  22. 65220, 65294, 65358, 65413, 65457, 65492, 65516, 65531,
  23. 65535, 65531, 65516, 65492, 65457, 65413, 65358, 65294,
  24. 65220, 65137, 65043, 64940, 64827, 64704, 64571, 64429,
  25. 64277, 64115, 63944, 63763, 63572, 63372, 63162, 62943,
  26. 62714, 62476, 62228, 61971, 61705, 61429, 61145, 60851,
  27. 60547, 60235, 59914, 59583, 59244, 58896, 58538, 58172,
  28. 57798, 57414, 57022, 56621, 56212, 55794, 55368, 54934,
  29. 54491, 54040, 53581, 53114, 52639, 52156, 51665, 51166,
  30. 50660, 50146, 49624, 49095, 48559, 48015, 47464, 46906,
  31. 46341, 45769, 45190, 44604, 44011, 43412, 42806, 42194,
  32. 41576, 40951, 40320, 39683, 39040, 38391, 37736, 37076,
  33. 36410, 35738, 35062, 34380, 33692, 33000, 32303, 31600,
  34. 30893, 30182, 29466, 28745, 28020, 27291, 26558, 25821,
  35. 25080, 24335, 23586, 22834, 22078, 21320, 20557, 19792,
  36. 19024, 18253, 17479, 16703, 15924, 15143, 14359, 13573,
  37. 12785, 11996, 11204, 10411, 9616, 8820, 8022, 7224,
  38. 6424, 5623, 4821, 4019, 3216, 2412, 1608, 804,
  39. };
  40. static uint64_t PlsrProfileHzToQ32(uint32_t hz)
  41. {
  42. return (uint64_t)hz << 32U;
  43. }
  44. static uint32_t PlsrProfileSqrtU64(uint64_t value)
  45. {
  46. uint64_t bit = UINT64_C(1) << 62U;
  47. uint64_t root = 0UL;
  48. while (bit > value)
  49. {
  50. bit >>= 2U;
  51. }
  52. while (bit != 0UL)
  53. {
  54. if (value >= root + bit)
  55. {
  56. value -= root + bit;
  57. root = (root >> 1U) + bit;
  58. }
  59. else
  60. {
  61. root >>= 1U;
  62. }
  63. bit >>= 2U;
  64. }
  65. return (uint32_t)root;
  66. }
  67. /* 每刷新步的斜率增量(Q32.32),支持 0.1ms 刷新(1000/refreshHz 可能 < 1)。 */
  68. static uint64_t PlsrProfileSlopePerStepQ32(uint32_t slopeHzPerMs,
  69. uint32_t refreshHz)
  70. {
  71. return PlsrProfileHzToQ32(slopeHzPerMs) * UINT64_C(1000)
  72. / (uint64_t)refreshHz;
  73. }
  74. /* 从当前频率减速到目标频率所需的脉冲数(Q32.32 精度)。 */
  75. static uint64_t PlsrProfileDecelPulsesQ32(uint32_t frequencyHz,
  76. uint32_t targetHz,
  77. uint32_t slopeHzPerMs)
  78. {
  79. uint64_t numerator;
  80. uint64_t denominator;
  81. if (frequencyHz <= targetHz)
  82. {
  83. return 0UL;
  84. }
  85. numerator = (uint64_t)frequencyHz * (uint64_t)frequencyHz
  86. - (uint64_t)targetHz * (uint64_t)targetHz;
  87. denominator = 2000UL * (uint64_t)slopeHzPerMs;
  88. if (denominator == 0UL)
  89. {
  90. return 0UL;
  91. }
  92. return (numerator / denominator) * PLSR_PROFILE_Q32_ONE
  93. + ((numerator % denominator) * PLSR_PROFILE_Q32_ONE)
  94. / denominator;
  95. }
  96. /* 直线增量初始化。 */
  97. static void PlsrProfileInitLinearDelta(PLSR_PROFILE_STATE *state,
  98. uint32_t slopeHzPerMs,
  99. uint32_t refreshHz)
  100. {
  101. state->deltaPerStepQ32 = PlsrProfileSlopePerStepQ32(slopeHzPerMs,
  102. refreshHz);
  103. state->jerkPerStepQ32 = 0UL;
  104. state->curveStep = 0U;
  105. state->curveStepLimit = 0U;
  106. state->sPhase = 0U;
  107. }
  108. /* S 形/正弦增量初始化:增量先升后降(S形)或正弦半波。 */
  109. static void PlsrProfileInitCurveDelta(PLSR_PROFILE_STATE *state,
  110. uint32_t frequencyGapHz,
  111. uint32_t slopeHzPerMs,
  112. uint32_t refreshHz,
  113. uint8_t curveMode)
  114. {
  115. uint64_t linearPerStep = PlsrProfileSlopePerStepQ32(slopeHzPerMs,
  116. refreshHz);
  117. uint64_t integerPerStepHz;
  118. uint64_t rampSteps;
  119. uint64_t jerkQ32;
  120. integerPerStepHz = ((uint64_t)slopeHzPerMs * UINT64_C(1000))
  121. / (uint64_t)refreshHz;
  122. if (integerPerStepHz == 0UL)
  123. {
  124. integerPerStepHz = 1UL;
  125. }
  126. rampSteps = ((uint64_t)frequencyGapHz + integerPerStepHz - 1UL)
  127. / integerPerStepHz;
  128. if (curveMode == PLSR_PROFILE_CURVE_SINE)
  129. {
  130. /* 正弦:时间同直线,峰值增量 = 直线增量 * pi/2(面积匹配)。 */
  131. state->deltaPerStepQ32 = 0UL;
  132. state->jerkPerStepQ32 = 0UL;
  133. state->curveStep = 0U;
  134. state->curveStepLimit = (uint32_t)rampSteps;
  135. state->sPhase = 0U;
  136. return;
  137. }
  138. /* S 形:增量 0→峰值→0,总时间 2 倍直线时间。 */
  139. jerkQ32 = linearPerStep / rampSteps;
  140. state->deltaPerStepQ32 = 0UL;
  141. state->jerkPerStepQ32 = jerkQ32;
  142. state->curveStep = 0U;
  143. state->curveStepLimit = (uint32_t)(rampSteps * 2UL);
  144. state->sPhase = 0U;
  145. }
  146. /* 进入加速段(直线或曲线)。 */
  147. static void PlsrProfileBeginAccel(PLSR_PROFILE_STATE *state)
  148. {
  149. uint32_t gapHz;
  150. if (state->targetFrequencyHz <= state->frequencyQ32 >> 32U)
  151. {
  152. state->phase = PLSR_PROFILE_PHASE_CRUISE;
  153. return;
  154. }
  155. if (state->curveMode == PLSR_PROFILE_CURVE_LINEAR)
  156. {
  157. PlsrProfileInitLinearDelta(state,
  158. state->accelSlopeHzPerMs,
  159. state->refreshHz);
  160. }
  161. else
  162. {
  163. gapHz = state->targetFrequencyHz
  164. - (uint32_t)(state->frequencyQ32 >> 32U);
  165. PlsrProfileInitCurveDelta(state,
  166. gapHz,
  167. state->accelSlopeHzPerMs,
  168. state->refreshHz,
  169. state->curveMode);
  170. }
  171. state->phase = PLSR_PROFILE_PHASE_ACCEL;
  172. }
  173. /* 进入减速段:减速到 decelTargetHz(默认=终止速度,降频时=新目标)。 */
  174. static void PlsrProfileBeginDecel(PLSR_PROFILE_STATE *state)
  175. {
  176. uint32_t gapHz;
  177. if (state->frequencyQ32 >> 32U <= state->decelTargetHz)
  178. {
  179. state->frequencyQ32 = PlsrProfileHzToQ32(state->decelTargetHz);
  180. if (state->decelTargetHz == state->stopFrequencyHz)
  181. {
  182. state->phase = PLSR_PROFILE_PHASE_DONE;
  183. }
  184. else
  185. {
  186. /* 降频到新目标:转匀速继续。 */
  187. state->targetFrequencyHz = state->decelTargetHz;
  188. state->decelTargetHz = state->stopFrequencyHz;
  189. state->phase = PLSR_PROFILE_PHASE_CRUISE;
  190. }
  191. return;
  192. }
  193. if (state->curveMode == PLSR_PROFILE_CURVE_LINEAR)
  194. {
  195. PlsrProfileInitLinearDelta(state,
  196. state->decelSlopeHzPerMs,
  197. state->refreshHz);
  198. }
  199. else
  200. {
  201. gapHz = (uint32_t)(state->frequencyQ32 >> 32U)
  202. - state->decelTargetHz;
  203. PlsrProfileInitCurveDelta(state,
  204. gapHz,
  205. state->decelSlopeHzPerMs,
  206. state->refreshHz,
  207. state->curveMode);
  208. }
  209. state->phase = PLSR_PROFILE_PHASE_DECEL;
  210. }
  211. /* 曲线模式下推进增量(S形三角增量 / 正弦查表)。 */
  212. static uint64_t PlsrProfileAdvanceDelta(PLSR_PROFILE_STATE *state,
  213. uint64_t linearPerStepQ32)
  214. {
  215. uint64_t delta;
  216. if (state->curveMode == PLSR_PROFILE_CURVE_SINE)
  217. {
  218. uint32_t index = ((uint32_t)state->curveStep * 256U)
  219. / (uint32_t)state->curveStepLimit;
  220. if (index > 255U)
  221. {
  222. index = 255U;
  223. }
  224. delta = ((uint64_t)PlsrProfileSineTable[index]
  225. * linearPerStepQ32) / 65536UL;
  226. }
  227. else
  228. {
  229. if (state->sPhase == 0U)
  230. {
  231. state->deltaPerStepQ32 += state->jerkPerStepQ32;
  232. if ((state->curveStepLimit != 0U)
  233. && (state->curveStep >= state->curveStepLimit / 2U))
  234. {
  235. state->sPhase = 1U;
  236. }
  237. }
  238. else
  239. {
  240. if (state->deltaPerStepQ32 > state->jerkPerStepQ32)
  241. {
  242. state->deltaPerStepQ32 -= state->jerkPerStepQ32;
  243. }
  244. else
  245. {
  246. state->deltaPerStepQ32 = 0UL;
  247. }
  248. }
  249. delta = state->deltaPerStepQ32;
  250. }
  251. state->curveStep++;
  252. return delta;
  253. }
  254. PLSR_RESULT PlsrProfileStart(PLSR_PROFILE_STATE *state,
  255. const PLSR_PROFILE_REQUEST *request,
  256. int64_t pulses,
  257. uint32_t refreshHz)
  258. {
  259. uint32_t startHz;
  260. if ((state == NULL) || (request == NULL))
  261. {
  262. return PLSR_RESULT_INVALID_ARGUMENT;
  263. }
  264. if ((pulses <= 0) || (refreshHz == 0UL)
  265. || (request->targetFrequencyHz == 0UL))
  266. {
  267. return PLSR_RESULT_INVALID_ARGUMENT;
  268. }
  269. state->refreshHz = refreshHz;
  270. state->totalPulses = pulses;
  271. state->targetFrequencyHz = request->targetFrequencyHz;
  272. if (request->targetFrequencyHz > request->maxFrequencyHz)
  273. {
  274. state->targetFrequencyHz = request->maxFrequencyHz;
  275. }
  276. state->startFrequencyHz = request->startFrequencyHz;
  277. state->stopFrequencyHz = request->stopFrequencyHz;
  278. state->decelTargetHz = request->stopFrequencyHz;
  279. state->accelSlopeHzPerMs = request->accelSlopeHzPerMs;
  280. state->decelSlopeHzPerMs = request->decelSlopeHzPerMs;
  281. state->curveMode = request->curveMode;
  282. startHz = request->startFrequencyHz;
  283. if (startHz > state->targetFrequencyHz)
  284. {
  285. startHz = state->targetFrequencyHz;
  286. }
  287. state->frequencyQ32 = PlsrProfileHzToQ32(startHz);
  288. state->emittedPulsesQ32 = 0UL;
  289. state->phase = PLSR_PROFILE_PHASE_ACCEL;
  290. state->started = 1U;
  291. if (startHz >= state->targetFrequencyHz)
  292. {
  293. state->phase = PLSR_PROFILE_PHASE_CRUISE;
  294. }
  295. else if (request->accelSlopeHzPerMs == 0UL)
  296. {
  297. state->frequencyQ32 = PlsrProfileHzToQ32(state->targetFrequencyHz);
  298. state->phase = PLSR_PROFILE_PHASE_CRUISE;
  299. }
  300. else
  301. {
  302. PlsrProfileBeginAccel(state);
  303. }
  304. return PLSR_RESULT_OK;
  305. }
  306. PLSR_RESULT PlsrProfileStep(PLSR_PROFILE_STATE *state,
  307. uint32_t *frequencyHz,
  308. uint8_t *completed)
  309. {
  310. uint64_t emittedThisStep;
  311. uint64_t remainingQ32;
  312. uint64_t decelNeeded;
  313. uint64_t linearPerStepQ32;
  314. uint64_t deltaQ32;
  315. uint32_t currentHz;
  316. if ((state == NULL) || (frequencyHz == NULL) || (completed == NULL))
  317. {
  318. return PLSR_RESULT_INVALID_ARGUMENT;
  319. }
  320. *completed = 0U;
  321. if (state->phase == PLSR_PROFILE_PHASE_DONE)
  322. {
  323. *frequencyHz = 0U;
  324. *completed = 1U;
  325. return PLSR_RESULT_OK;
  326. }
  327. linearPerStepQ32 = PlsrProfileSlopePerStepQ32(
  328. (state->phase == PLSR_PROFILE_PHASE_ACCEL)
  329. ? state->accelSlopeHzPerMs
  330. : state->decelSlopeHzPerMs,
  331. state->refreshHz);
  332. switch (state->phase)
  333. {
  334. case PLSR_PROFILE_PHASE_ACCEL:
  335. deltaQ32 = PlsrProfileAdvanceDelta(state, linearPerStepQ32);
  336. state->frequencyQ32 += deltaQ32;
  337. if ((state->frequencyQ32
  338. >= PlsrProfileHzToQ32(state->targetFrequencyHz))
  339. || ((state->curveMode != PLSR_PROFILE_CURVE_LINEAR)
  340. && (state->curveStep >= state->curveStepLimit)))
  341. {
  342. state->frequencyQ32 =
  343. PlsrProfileHzToQ32(state->targetFrequencyHz);
  344. state->phase = PLSR_PROFILE_PHASE_CRUISE;
  345. }
  346. break;
  347. case PLSR_PROFILE_PHASE_CRUISE:
  348. /* 剩余脉冲不足以按当前频率完成减速时开始减速(Q32 精度)。 */
  349. remainingQ32 = PlsrProfileHzToQ32(
  350. (uint32_t)state->totalPulses)
  351. - state->emittedPulsesQ32;
  352. decelNeeded = PlsrProfileDecelPulsesQ32(
  353. (uint32_t)(state->frequencyQ32 >> 32U),
  354. state->stopFrequencyHz,
  355. state->decelSlopeHzPerMs);
  356. if (remainingQ32 <= decelNeeded)
  357. {
  358. PlsrProfileBeginDecel(state);
  359. }
  360. break;
  361. case PLSR_PROFILE_PHASE_DECEL:
  362. deltaQ32 = PlsrProfileAdvanceDelta(state, linearPerStepQ32);
  363. state->frequencyQ32 -= deltaQ32;
  364. if (state->frequencyQ32
  365. <= PlsrProfileHzToQ32(state->decelTargetHz))
  366. {
  367. state->frequencyQ32 =
  368. PlsrProfileHzToQ32(state->decelTargetHz);
  369. if (state->decelTargetHz == state->stopFrequencyHz)
  370. {
  371. state->phase = PLSR_PROFILE_PHASE_DONE;
  372. }
  373. else
  374. {
  375. /* 降频到新目标:转匀速继续。 */
  376. state->targetFrequencyHz = state->decelTargetHz;
  377. state->decelTargetHz = state->stopFrequencyHz;
  378. state->phase = PLSR_PROFILE_PHASE_CRUISE;
  379. }
  380. }
  381. break;
  382. default:
  383. break;
  384. }
  385. /* 发射本步脉冲:频率(Hz) / 刷新率。 */
  386. currentHz = (uint32_t)(state->frequencyQ32 >> 32U);
  387. emittedThisStep = state->frequencyQ32 / (uint64_t)state->refreshHz;
  388. if ((state->emittedPulsesQ32 + emittedThisStep)
  389. >= PlsrProfileHzToQ32((uint32_t)state->totalPulses))
  390. {
  391. state->emittedPulsesQ32 =
  392. PlsrProfileHzToQ32((uint32_t)state->totalPulses);
  393. state->phase = PLSR_PROFILE_PHASE_DONE;
  394. }
  395. else
  396. {
  397. state->emittedPulsesQ32 += emittedThisStep;
  398. }
  399. *frequencyHz = currentHz;
  400. if (state->phase == PLSR_PROFILE_PHASE_DONE)
  401. {
  402. *completed = 1U;
  403. *frequencyHz = 0U;
  404. }
  405. return PLSR_RESULT_OK;
  406. }
  407. PLSR_RESULT PlsrProfileRetarget(PLSR_PROFILE_STATE *state,
  408. uint32_t newTargetFrequencyHz)
  409. {
  410. uint32_t currentHz;
  411. if (state == NULL)
  412. {
  413. return PLSR_RESULT_INVALID_ARGUMENT;
  414. }
  415. if (newTargetFrequencyHz == 0UL)
  416. {
  417. return PLSR_RESULT_INVALID_ARGUMENT;
  418. }
  419. currentHz = (uint32_t)(state->frequencyQ32 >> 32U);
  420. if (newTargetFrequencyHz == state->targetFrequencyHz)
  421. {
  422. return PLSR_RESULT_OK;
  423. }
  424. state->targetFrequencyHz = newTargetFrequencyHz;
  425. if (newTargetFrequencyHz > currentHz)
  426. {
  427. /* 升频:加速/匀速 → 加速;减速中 → 取消减速转加速。 */
  428. if ((state->phase == PLSR_PROFILE_PHASE_DECEL)
  429. || (state->phase == PLSR_PROFILE_PHASE_CRUISE)
  430. || (state->phase == PLSR_PROFILE_PHASE_DONE))
  431. {
  432. PlsrProfileBeginAccel(state);
  433. }
  434. }
  435. else
  436. {
  437. /* 降频:先减速到新目标,再转匀速继续(最终仍减速到终止速度)。 */
  438. if ((state->phase == PLSR_PROFILE_PHASE_ACCEL)
  439. || (state->phase == PLSR_PROFILE_PHASE_CRUISE))
  440. {
  441. state->decelTargetHz = newTargetFrequencyHz;
  442. PlsrProfileBeginDecel(state);
  443. }
  444. }
  445. return PLSR_RESULT_OK;
  446. }
  447. PLSR_RESULT PlsrProfileRequestStop(PLSR_PROFILE_STATE *state)
  448. {
  449. if ((state == NULL) || (state->started == 0U))
  450. {
  451. return PLSR_RESULT_INVALID_ARGUMENT;
  452. }
  453. state->stopFrequencyHz = 0U;
  454. state->decelTargetHz = 0U;
  455. if (state->decelSlopeHzPerMs == 0UL)
  456. {
  457. state->frequencyQ32 = 0UL;
  458. state->phase = PLSR_PROFILE_PHASE_DONE;
  459. }
  460. else
  461. {
  462. PlsrProfileBeginDecel(state);
  463. }
  464. return PLSR_RESULT_OK;
  465. }
  466. PLSR_RESULT PlsrProfilePlan(const PLSR_PROFILE_REQUEST *request,
  467. int64_t pulses,
  468. PLSR_PROFILE_PLAN *plan)
  469. {
  470. double target;
  471. double start;
  472. double stop;
  473. double accelSlope;
  474. double decelSlope;
  475. double accelTime;
  476. double decelTime;
  477. double accelPulses;
  478. double decelPulses;
  479. double cruisePulses;
  480. double cruiseTime;
  481. double peak;
  482. if ((request == NULL) || (plan == NULL) || (pulses <= 0))
  483. {
  484. return PLSR_RESULT_INVALID_ARGUMENT;
  485. }
  486. (void)memset(plan, 0, sizeof(*plan));
  487. target = (double)request->targetFrequencyHz;
  488. if (target > (double)request->maxFrequencyHz)
  489. {
  490. target = (double)request->maxFrequencyHz;
  491. }
  492. start = (double)request->startFrequencyHz;
  493. if (start > target)
  494. {
  495. start = target;
  496. }
  497. stop = (double)request->stopFrequencyHz;
  498. accelSlope = (double)request->accelSlopeHzPerMs;
  499. decelSlope = (double)request->decelSlopeHzPerMs;
  500. accelTime = (target > start) ? (target - start) / accelSlope : 0.0;
  501. decelTime = (target > stop) ? (target - stop) / decelSlope : 0.0;
  502. accelPulses = (start + target) * accelTime / 2000.0;
  503. decelPulses = (target + stop) * decelTime / 2000.0;
  504. if ((accelPulses + decelPulses) >= (double)pulses)
  505. {
  506. /* 三角曲线:求峰值频率。 */
  507. double sum = (double)pulses * 1000.0
  508. + start * start / (2.0 * accelSlope)
  509. + stop * stop / (2.0 * decelSlope);
  510. double denom = 1.0 / (2.0 * accelSlope)
  511. + 1.0 / (2.0 * decelSlope);
  512. peak = (denom > 0.0) ? sqrt(sum / denom) : target;
  513. accelTime = (peak > start) ? (peak - start) / accelSlope : 0.0;
  514. decelTime = (peak > stop) ? (peak - stop) / decelSlope : 0.0;
  515. accelPulses = (start + peak) * accelTime / 2000.0;
  516. decelPulses = (peak + stop) * decelTime / 2000.0;
  517. plan->peakFrequencyHz = (uint32_t)peak;
  518. plan->triangular = 1U;
  519. }
  520. else
  521. {
  522. cruisePulses = (double)pulses - accelPulses - decelPulses;
  523. cruiseTime = (target > 0.0) ? cruisePulses * 1000.0 / target : 0.0;
  524. plan->cruiseTimeMs = (uint32_t)cruiseTime;
  525. plan->peakFrequencyHz = (uint32_t)target;
  526. plan->triangular = 0U;
  527. }
  528. plan->accelTimeMs = (uint32_t)accelTime;
  529. plan->decelTimeMs = (uint32_t)decelTime;
  530. plan->totalTimeMs = plan->accelTimeMs + plan->cruiseTimeMs
  531. + plan->decelTimeMs;
  532. plan->totalPulses = pulses;
  533. return PLSR_RESULT_OK;
  534. }
  535. /* 虚拟发射计数校准到硬件实际计数。
  536. * ARPE 预装载使硬件频率切换滞后于 profile 理想频率(约一个周期),
  537. * 不校准会导致虚拟计数提前到达 totalPulses:profile DONE 时硬件仍欠发,
  538. * PWM 以 DONE 瞬间的冻结频率补发剩余脉冲(段尾低频平台/宽脉冲)。
  539. * 每刷新周期由 core 在 Step 前调用,偏差不跨周期累积。 */
  540. void PlsrProfileSyncPulses(PLSR_PROFILE_STATE *state, uint64_t hwPulses)
  541. {
  542. if (state == NULL)
  543. {
  544. return;
  545. }
  546. state->emittedPulsesQ32 = hwPulses << 32U;
  547. }
  548. uint32_t PlsrProfileGetInitialOutputFrequency(
  549. const PLSR_PROFILE_STATE *state)
  550. {
  551. uint64_t accelerationHzPerSecond;
  552. uint64_t pulseDiscriminant;
  553. uint64_t targetSquare;
  554. uint64_t currentSquare;
  555. uint64_t denominator;
  556. uint32_t currentHz;
  557. uint32_t endHz;
  558. uint32_t result;
  559. if (state == NULL)
  560. {
  561. return 0UL;
  562. }
  563. currentHz = (uint32_t)(state->frequencyQ32 >> 32U);
  564. if ((state->phase != PLSR_PROFILE_PHASE_ACCEL)
  565. || (state->curveMode != PLSR_PROFILE_CURVE_LINEAR)
  566. || (state->accelSlopeHzPerMs == 0UL)
  567. || (currentHz >= state->targetFrequencyHz))
  568. {
  569. return currentHz;
  570. }
  571. accelerationHzPerSecond =
  572. (uint64_t)state->accelSlopeHzPerMs * UINT64_C(1000);
  573. currentSquare = (uint64_t)currentHz * currentHz;
  574. targetSquare = (uint64_t)state->targetFrequencyHz
  575. * state->targetFrequencyHz;
  576. pulseDiscriminant = currentSquare
  577. + UINT64_C(2) * accelerationHzPerSecond;
  578. if (pulseDiscriminant <= targetSquare)
  579. {
  580. /* 整个首脉冲都处于线性加速段:f1^2=f0^2+2a。 */
  581. endHz = PlsrProfileSqrtU64(pulseDiscriminant);
  582. result = (currentHz + endHz) / 2UL;
  583. }
  584. else
  585. {
  586. /* 不到一个脉冲就到达目标频率:剩余相位按目标频率运行。 */
  587. uint64_t gap = (uint64_t)state->targetFrequencyHz - currentHz;
  588. denominator = gap * gap + UINT64_C(2) * accelerationHzPerSecond;
  589. result = (uint32_t)((UINT64_C(2) * accelerationHzPerSecond
  590. * state->targetFrequencyHz)
  591. / denominator);
  592. }
  593. if (result == 0UL)
  594. {
  595. result = 1UL;
  596. }
  597. if (result > state->targetFrequencyHz)
  598. {
  599. result = state->targetFrequencyHz;
  600. }
  601. return result;
  602. }
  603. uint32_t PlsrProfileGetBrakingOutputFrequency(
  604. const PLSR_PROFILE_STATE *state,
  605. uint64_t pulsesRemaining)
  606. {
  607. uint64_t decelerationHzPerSecond;
  608. uint64_t twiceDeceleration;
  609. uint64_t stopSquare;
  610. uint64_t targetSquare;
  611. uint64_t brakingSquare;
  612. uint64_t brakingPulses;
  613. uint64_t startSquare;
  614. uint64_t endSquare;
  615. uint32_t startHz;
  616. uint32_t endHz;
  617. uint32_t result;
  618. if ((state == NULL) || (pulsesRemaining == 0UL))
  619. {
  620. return 0UL;
  621. }
  622. if ((state->curveMode != PLSR_PROFILE_CURVE_LINEAR)
  623. || (state->decelSlopeHzPerMs == 0UL))
  624. {
  625. return state->targetFrequencyHz;
  626. }
  627. decelerationHzPerSecond =
  628. (uint64_t)state->decelSlopeHzPerMs * UINT64_C(1000);
  629. twiceDeceleration = UINT64_C(2) * decelerationHzPerSecond;
  630. stopSquare = (uint64_t)state->stopFrequencyHz
  631. * state->stopFrequencyHz;
  632. targetSquare = (uint64_t)state->targetFrequencyHz
  633. * state->targetFrequencyHz;
  634. if (targetSquare <= stopSquare)
  635. {
  636. return state->targetFrequencyHz;
  637. }
  638. /* 先比较制动距离,再做乘法。这样超长路径直接保持目标频率,
  639. * 同时避免 2*a*n 在极端脉冲数下发生 uint64_t 溢出。 */
  640. brakingSquare = targetSquare - stopSquare;
  641. brakingPulses = brakingSquare / twiceDeceleration;
  642. if ((brakingSquare % twiceDeceleration) != 0UL)
  643. {
  644. brakingPulses++;
  645. }
  646. if (pulsesRemaining > brakingPulses)
  647. {
  648. return state->targetFrequencyHz;
  649. }
  650. startSquare = stopSquare
  651. + twiceDeceleration * pulsesRemaining;
  652. endSquare = stopSquare
  653. + twiceDeceleration * (pulsesRemaining - 1UL);
  654. startHz = PlsrProfileSqrtU64(startSquare);
  655. endHz = PlsrProfileSqrtU64(endSquare);
  656. result = (startHz + endHz) / 2UL;
  657. if (result < state->stopFrequencyHz)
  658. {
  659. result = state->stopFrequencyHz;
  660. }
  661. if (result > state->targetFrequencyHz)
  662. {
  663. result = state->targetFrequencyHz;
  664. }
  665. if (result == 0UL)
  666. {
  667. result = 1UL;
  668. }
  669. return result;
  670. }