Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 
 
 
 

1048 righe
36 KiB

  1. #include "plsr_planner.h"
  2. #include <stddef.h>
  3. #include <string.h>
  4. #define PLSR_PLANNER_Q32_ONE (4294967296ULL)
  5. static const uint32_t PlsrPlannerSmoothIntegralQ24[65] =
  6. {
  7. 0UL, 64UL, 504UL, 1688UL, 3968UL, 7688UL, 13176UL, 20752UL,
  8. 30720UL, 43376UL, 59000UL, 77864UL, 100224UL, 126328UL, 156408UL,
  9. 190688UL, 229376UL, 272672UL, 320760UL, 373816UL, 432000UL,
  10. 495464UL, 564344UL, 638768UL, 718848UL, 804688UL, 896376UL,
  11. 993992UL, 1097600UL, 1207256UL, 1323000UL, 1444864UL, 1572864UL,
  12. 1707008UL, 1847288UL, 1993688UL, 2146176UL, 2304712UL, 2469240UL,
  13. 2639696UL, 2816000UL, 2998064UL, 3185784UL, 3379048UL, 3577728UL,
  14. 3781688UL, 3990776UL, 4204832UL, 4423680UL, 4647136UL, 4875000UL,
  15. 5107064UL, 5343104UL, 5582888UL, 5826168UL, 6072688UL, 6322176UL,
  16. 6574352UL, 6828920UL, 7085576UL, 7344000UL, 7603864UL, 7864824UL,
  17. 8126528UL, 8388608UL
  18. };
  19. static const uint32_t PlsrPlannerSineIntegralQ24[65] =
  20. {
  21. 0UL, 53UL, 421UL, 1420UL, 3362UL, 6560UL, 11321UL, 17949UL,
  22. 26744UL, 38000UL, 52007UL, 69047UL, 89393UL, 113314UL, 141066UL,
  23. 172899UL, 209052UL, 249753UL, 295221UL, 345662UL, 401269UL,
  24. 462225UL, 528698UL, 600845UL, 678806UL, 762711UL, 852672UL,
  25. 948789UL, 1051146UL, 1159812UL, 1274841UL, 1396271UL, 1524127UL,
  26. 1658415UL, 1799129UL, 1946244UL, 2099722UL, 2259509UL, 2425536UL,
  27. 2597719UL, 2775958UL, 2960141UL, 3150138UL, 3345809UL, 3546997UL,
  28. 3753534UL, 3965237UL, 4181913UL, 4403356UL, 4629347UL, 4859658UL,
  29. 5094050UL, 5332273UL, 5574071UL, 5819175UL, 6067312UL, 6318200UL,
  30. 6571549UL, 6827065UL, 7084448UL, 7343394UL, 7603596UL, 7864741UL,
  31. 8126517UL, 8388608UL
  32. };
  33. static uint32_t PlsrPlannerAbsDifference(uint32_t first, uint32_t second)
  34. {
  35. return (first > second) ? (first - second) : (second - first);
  36. }
  37. static uint32_t PlsrPlannerRampTime(const PLSR_MOTION_BLOCK *block,uint32_t fromHz, uint32_t toHz)
  38. {
  39. uint32_t baseTimeMs;
  40. uint64_t durationMs;
  41. if (fromHz == toHz)
  42. {
  43. return 0UL;
  44. }
  45. baseTimeMs = (toHz > fromHz) ? block->accelerationTimeMs
  46. : block->decelerationTimeMs;
  47. if (baseTimeMs == 0UL)
  48. {
  49. return 0UL;
  50. }
  51. durationMs = ((uint64_t)PlsrPlannerAbsDifference(fromHz, toHz)
  52. * baseTimeMs + block->referenceSpeedHz - 1UL)
  53. / block->referenceSpeedHz;
  54. return (durationMs > 0xFFFFFFFFULL) ? 0xFFFFFFFFUL
  55. : (uint32_t)durationMs;
  56. }
  57. static uint16_t PlsrPlannerBaseRampTime(const PLSR_MOTION_BLOCK *block,
  58. uint32_t fromHz,
  59. uint32_t toHz)
  60. {
  61. if (toHz > fromHz)
  62. {
  63. return block->accelerationTimeMs;
  64. }
  65. if (toHz < fromHz)
  66. {
  67. return block->decelerationTimeMs;
  68. }
  69. return 0U;
  70. }
  71. static uint64_t PlsrPlannerRampWeight(uint32_t fromHz,
  72. uint32_t toHz,
  73. uint16_t baseTimeMs)
  74. {
  75. uint64_t fromSquared = (uint64_t)fromHz * fromHz;
  76. uint64_t toSquared = (uint64_t)toHz * toHz;
  77. uint64_t difference = (fromSquared > toSquared)
  78. ? (fromSquared - toSquared)
  79. : (toSquared - fromSquared);
  80. return difference * baseTimeMs;
  81. }
  82. static uint64_t PlsrPlannerRequiredPulses(const PLSR_MOTION_BLOCK *block,
  83. uint64_t rampWeight)
  84. {
  85. uint64_t denominator = (uint64_t)2U * block->referenceSpeedHz * 1000UL;
  86. return (rampWeight == 0ULL) ? 0ULL
  87. : (rampWeight + denominator - 1ULL)
  88. / denominator;
  89. }
  90. static uint32_t PlsrPlannerIntegerSquareRoot(uint64_t value)
  91. {
  92. uint64_t bit = (uint64_t)1U << 62U;
  93. uint64_t root = 0ULL;
  94. while (bit > value)
  95. {
  96. bit >>= 2U;
  97. }
  98. while (bit != 0ULL)
  99. {
  100. if (value >= root + bit)
  101. {
  102. value -= root + bit;
  103. root = (root >> 1U) + bit;
  104. }
  105. else
  106. {
  107. root >>= 1U;
  108. }
  109. bit >>= 2U;
  110. }
  111. return (uint32_t)root;
  112. }
  113. static uint32_t PlsrPlannerReachableFrequency(
  114. const PLSR_MOTION_BLOCK *block,
  115. uint32_t fromHz,
  116. uint32_t towardHz,
  117. uint32_t pulseCount)
  118. {
  119. uint16_t baseTimeMs = PlsrPlannerBaseRampTime(block, fromHz, towardHz);
  120. uint64_t frequencySquared = (uint64_t)fromHz * fromHz;
  121. uint64_t changeSquared;
  122. uint32_t reachableHz;
  123. if ((baseTimeMs == 0U) || (fromHz == towardHz))
  124. {
  125. return towardHz;
  126. }
  127. changeSquared = (uint64_t)2U * pulseCount * block->referenceSpeedHz
  128. * 1000UL / baseTimeMs;
  129. if (towardHz > fromHz)
  130. {
  131. reachableHz = PlsrPlannerIntegerSquareRoot(
  132. frequencySquared + changeSquared);
  133. return (reachableHz > towardHz) ? towardHz : reachableHz;
  134. }
  135. frequencySquared = (changeSquared >= frequencySquared)
  136. ? 0ULL : (frequencySquared - changeSquared);
  137. reachableHz = PlsrPlannerIntegerSquareRoot(frequencySquared);
  138. if ((uint64_t)reachableHz * reachableHz < frequencySquared)
  139. {
  140. reachableHz++;
  141. }
  142. return (reachableHz < towardHz) ? towardHz : reachableHz;
  143. }
  144. static uint32_t PlsrPlannerPeak(const PLSR_MOTION_BLOCK *block,
  145. uint32_t startHz,
  146. uint32_t endHz)
  147. {
  148. uint32_t targetHz = block->cruiseHz;
  149. uint32_t upperEndpoint = (startHz > endHz) ? startHz : endHz;
  150. uint32_t lowerEndpoint = (startHz < endHz) ? startHz : endHz;
  151. uint16_t entryTimeMs;
  152. uint16_t exitTimeMs;
  153. uint32_t timeSumMs;
  154. uint64_t weightedEndpoints;
  155. uint64_t availableArea;
  156. uint64_t peakSquared;
  157. uint32_t peakHz;
  158. if ((targetHz <= upperEndpoint) && (targetHz >= lowerEndpoint))
  159. {
  160. return targetHz;
  161. }
  162. entryTimeMs = PlsrPlannerBaseRampTime(block, startHz, targetHz);
  163. exitTimeMs = PlsrPlannerBaseRampTime(block, targetHz, endHz);
  164. timeSumMs = (uint32_t)entryTimeMs + exitTimeMs;
  165. if (timeSumMs == 0UL)
  166. {
  167. return targetHz;
  168. }
  169. weightedEndpoints = (uint64_t)startHz * startHz * entryTimeMs
  170. + (uint64_t)endHz * endHz * exitTimeMs;
  171. availableArea = (uint64_t)2U * block->pulseBudget
  172. * block->referenceSpeedHz * 1000UL;
  173. if (targetHz > upperEndpoint)
  174. {
  175. peakSquared = (availableArea + weightedEndpoints) / timeSumMs;
  176. peakHz = PlsrPlannerIntegerSquareRoot(peakSquared);
  177. if (peakHz < upperEndpoint)
  178. {
  179. peakHz = upperEndpoint;
  180. }
  181. return (peakHz > targetHz) ? targetHz : peakHz;
  182. }
  183. if (availableArea >= weightedEndpoints)
  184. {
  185. return targetHz;
  186. }
  187. peakSquared = (weightedEndpoints - availableArea) / timeSumMs;
  188. peakHz = PlsrPlannerIntegerSquareRoot(peakSquared);
  189. if (peakHz < targetHz)
  190. {
  191. peakHz = targetHz;
  192. }
  193. return (peakHz > lowerEndpoint) ? lowerEndpoint : peakHz;
  194. }
  195. //C(x)函数
  196. //瞬时速度=delta*C(x)
  197. static uint64_t PlsrPlannerCurveIntegralQ32(uint64_t progressQ32,
  198. uint16_t curveMode)
  199. {
  200. const uint32_t *table;
  201. uint64_t scaled;
  202. uint32_t index;
  203. uint32_t fraction;
  204. uint64_t first;
  205. uint64_t second;
  206. if (progressQ32 >= PLSR_PLANNER_Q32_ONE)
  207. {
  208. return PLSR_PLANNER_Q32_ONE / 2ULL;
  209. }
  210. if (curveMode == 0U)
  211. {
  212. return (progressQ32 * progressQ32) >> 33U;
  213. }
  214. table = (curveMode == 1U) ? PlsrPlannerSmoothIntegralQ24
  215. : PlsrPlannerSineIntegralQ24;
  216. scaled = progressQ32 * 64ULL;
  217. index = (uint32_t)(scaled >> 32U);
  218. fraction = (uint32_t)scaled;
  219. first = (uint64_t)table[index] << 8U;
  220. second = (uint64_t)table[index + 1UL] << 8U;
  221. return first + (((second - first) * fraction) >> 32U);
  222. }
  223. static uint64_t PlsrPlannerRampAreaQ32(const PLSR_PLANNER_CONTEXT *context,
  224. uint32_t fromHz,
  225. uint32_t toHz,
  226. uint64_t progressQ32)
  227. {
  228. int64_t delta = (int64_t)toHz - (int64_t)fromHz;
  229. int64_t area = (int64_t)((uint64_t)fromHz * progressQ32)
  230. + delta * (int64_t)PlsrPlannerCurveIntegralQ32(
  231. progressQ32, context->block.curveMode);
  232. return (uint64_t)area;
  233. }
  234. static uint64_t PlsrPlannerExactBoundaryQ32(
  235. const PLSR_PLANNER_CONTEXT *context,
  236. uint64_t previousBoundaryQ32,
  237. uint64_t targetAreaQ32)
  238. {
  239. uint64_t lowerQ32 = previousBoundaryQ32;
  240. uint64_t upperQ32 = PLSR_PLANNER_Q32_ONE;
  241. uint64_t middleQ32;
  242. uint32_t iteration;
  243. for (iteration = 0UL; iteration < 32UL; iteration++)
  244. {
  245. middleQ32 = lowerQ32 + ((upperQ32 - lowerQ32) >> 1U);
  246. if (PlsrPlannerRampAreaQ32(context, context->rampFromHz,
  247. context->rampToHz, middleQ32)
  248. < targetAreaQ32)
  249. {
  250. lowerQ32 = middleQ32;
  251. }
  252. else
  253. {
  254. upperQ32 = middleQ32;
  255. }
  256. }
  257. return upperQ32;
  258. }
  259. static uint32_t PlsrPlannerInstantFrequency(
  260. const PLSR_PLANNER_CONTEXT *context,
  261. uint64_t progressQ32)
  262. {
  263. const uint32_t *table;
  264. uint64_t scaled;
  265. uint64_t curveProgressQ32;
  266. uint32_t index;
  267. uint32_t gap;
  268. if (progressQ32 >= PLSR_PLANNER_Q32_ONE)
  269. {
  270. return context->rampToHz;
  271. }
  272. if (context->block.curveMode == 0U)
  273. {
  274. curveProgressQ32 = progressQ32;
  275. }
  276. else
  277. {
  278. table = (context->block.curveMode == 1U)
  279. ? PlsrPlannerSmoothIntegralQ24
  280. : PlsrPlannerSineIntegralQ24;
  281. scaled = progressQ32 * 64ULL;
  282. index = (uint32_t)(scaled >> 32U);
  283. curveProgressQ32 =
  284. (uint64_t)(table[index + 1UL] - table[index]) << 14U;
  285. }
  286. if (context->rampToHz >= context->rampFromHz)
  287. {
  288. gap = context->rampToHz - context->rampFromHz;
  289. return context->rampFromHz
  290. + (uint32_t)(((uint64_t)gap * curveProgressQ32) >> 32U);
  291. }
  292. gap = context->rampFromHz - context->rampToHz;
  293. return context->rampFromHz
  294. - (uint32_t)(((uint64_t)gap * curveProgressQ32) >> 32U);
  295. }
  296. static uint64_t PlsrPlannerPredictedBoundaryQ32(
  297. const PLSR_PLANNER_CONTEXT *context,
  298. uint64_t targetAreaQ32)
  299. {
  300. uint64_t previousQ32 = context->rampBoundaryQ32;
  301. uint64_t currentAreaQ32 = (previousQ32 == 0ULL)
  302. ? 0ULL
  303. : PlsrPlannerRampAreaQ32(
  304. context, context->rampFromHz,
  305. context->rampToHz, previousQ32);
  306. uint64_t candidateQ32;
  307. uint64_t candidateAreaQ32;
  308. uint64_t differenceQ32;
  309. uint64_t correctionQ32;
  310. uint32_t derivativeHz;
  311. if (context->rampLastPhaseStepQ32
  312. >= PLSR_PLANNER_Q32_ONE - previousQ32)
  313. {
  314. candidateQ32 = PLSR_PLANNER_Q32_ONE;
  315. }
  316. else if (context->rampLastPhaseStepQ32 != 0ULL)
  317. {
  318. candidateQ32 = previousQ32 + context->rampLastPhaseStepQ32;
  319. }
  320. else
  321. {
  322. derivativeHz = PlsrPlannerInstantFrequency(context, previousQ32);
  323. if (derivativeHz == 0UL)
  324. {
  325. derivativeHz = 1UL;
  326. }
  327. differenceQ32 = targetAreaQ32 - currentAreaQ32;
  328. correctionQ32 = (differenceQ32 + derivativeHz - 1UL)
  329. / derivativeHz;
  330. candidateQ32 = (correctionQ32
  331. >= PLSR_PLANNER_Q32_ONE - previousQ32)
  332. ? PLSR_PLANNER_Q32_ONE
  333. : previousQ32 + correctionQ32;
  334. }
  335. candidateAreaQ32 = PlsrPlannerRampAreaQ32(
  336. context, context->rampFromHz, context->rampToHz, candidateQ32);
  337. derivativeHz = PlsrPlannerInstantFrequency(context, candidateQ32);
  338. if (derivativeHz == 0UL)
  339. {
  340. derivativeHz = 1UL;
  341. }
  342. if (candidateAreaQ32 < targetAreaQ32)
  343. {
  344. differenceQ32 = targetAreaQ32 - candidateAreaQ32;
  345. correctionQ32 = (differenceQ32 + derivativeHz - 1UL)
  346. / derivativeHz;
  347. candidateQ32 = (correctionQ32
  348. >= PLSR_PLANNER_Q32_ONE - candidateQ32)
  349. ? PLSR_PLANNER_Q32_ONE
  350. : candidateQ32 + correctionQ32;
  351. }
  352. else if (candidateAreaQ32 > targetAreaQ32)
  353. {
  354. differenceQ32 = candidateAreaQ32 - targetAreaQ32;
  355. correctionQ32 = differenceQ32 / derivativeHz;
  356. if (correctionQ32 == 0ULL)
  357. {
  358. correctionQ32 = 1ULL;
  359. }
  360. candidateQ32 = (correctionQ32 >= candidateQ32 - previousQ32)
  361. ? previousQ32 + 1ULL
  362. : candidateQ32 - correctionQ32;
  363. }
  364. return candidateQ32;
  365. }
  366. static void PlsrPlannerStartRamp(PLSR_PLANNER_CONTEXT *context,
  367. uint8_t rampKind,
  368. uint32_t fromHz,
  369. uint32_t toHz,
  370. uint32_t pulseCount)
  371. {
  372. context->rampKind = rampKind;
  373. context->rampRelativePulse = 0UL;
  374. context->rampPulseCount = pulseCount;
  375. context->rampFromHz = fromHz;
  376. context->rampToHz = toHz;
  377. context->rampDurationMs = PlsrPlannerRampTime(&context->block, fromHz, toHz);
  378. context->rampTotalAreaQ32 = PlsrPlannerRampAreaQ32(
  379. context, fromHz, toHz, PLSR_PLANNER_Q32_ONE);
  380. context->rampAreaStepQ32 = context->rampTotalAreaQ32 / pulseCount;
  381. context->rampAreaRemainder =
  382. (uint32_t)(context->rampTotalAreaQ32 % pulseCount);
  383. context->rampRemainderAccumulator = 0UL;
  384. context->rampTargetAreaQ32 = 0ULL;
  385. context->rampBoundaryQ32 = 0ULL;
  386. context->rampActualTimeQ32 = 0ULL;
  387. context->rampLastPhaseStepQ32 = 0ULL;
  388. context->lastRampHz = 0UL;
  389. context->rampFirstBoundaryQ32 = PlsrPlannerExactBoundaryQ32(
  390. context, 0ULL, context->rampAreaStepQ32);
  391. if (pulseCount > 1UL)
  392. {
  393. uint64_t secondTargetAreaQ32 = context->rampAreaStepQ32 * 2ULL
  394. + ((uint64_t)context->rampAreaRemainder * 2ULL) / pulseCount;
  395. context->rampSecondBoundaryQ32 = PlsrPlannerExactBoundaryQ32(
  396. context, context->rampFirstBoundaryQ32,
  397. secondTargetAreaQ32);
  398. }
  399. else
  400. {
  401. context->rampSecondBoundaryQ32 = PLSR_PLANNER_Q32_ONE;
  402. }
  403. }
  404. static uint8_t PlsrPlannerSameSetting(
  405. const PLSR_PLATFORM_TIMER_SETTING *first,
  406. const PLSR_PLATFORM_TIMER_SETTING *second)
  407. {
  408. return ((first->actualFrequencyHz == second->actualFrequencyHz)
  409. && (first->prescaler == second->prescaler)
  410. && (first->pairPrescaler == second->pairPrescaler)
  411. && (first->period == second->period)
  412. && (first->compare == second->compare)) ? 1U : 0U;
  413. }
  414. static uint8_t PlsrPlannerBuildStep(PLSR_PLANNER_CONTEXT *context,
  415. uint32_t requestedHz,
  416. PLSR_PLATFORM_TIMER_SETTING *setting,
  417. uint32_t *normalizedRequestedHz)
  418. {
  419. if (requestedHz == 0UL)
  420. {
  421. requestedHz = 1UL;
  422. }
  423. if (requestedHz > PLSR_FREQUENCY_MAX_HZ)
  424. {
  425. requestedHz = PLSR_FREQUENCY_MAX_HZ;
  426. }
  427. *normalizedRequestedHz = requestedHz;
  428. return PlsrPlatformBuildTimerSetting(context->block.pulseOutput,
  429. PLSR_OUTPUT_PULSE_DIR,
  430. requestedHz, setting);
  431. }
  432. static uint8_t PlsrPlannerTakeRampStep(
  433. PLSR_PLANNER_CONTEXT *context,
  434. PLSR_PLATFORM_TIMER_SETTING *setting,
  435. uint32_t *requestedFrequencyHz)
  436. {
  437. uint64_t nextBoundaryQ32;
  438. uint64_t desiredDeltaQ32;
  439. uint64_t denominator;
  440. uint64_t requestedHz;
  441. uint64_t actualDeltaQ32;
  442. context->rampTargetAreaQ32 += context->rampAreaStepQ32;
  443. context->rampRemainderAccumulator += context->rampAreaRemainder;
  444. if (context->rampRemainderAccumulator >= context->rampPulseCount)
  445. {
  446. context->rampTargetAreaQ32++;
  447. context->rampRemainderAccumulator -= context->rampPulseCount;
  448. }
  449. if (context->rampRelativePulse + 1UL >= context->rampPulseCount)
  450. {
  451. context->rampTargetAreaQ32 = context->rampTotalAreaQ32;
  452. nextBoundaryQ32 = PLSR_PLANNER_Q32_ONE;
  453. }
  454. else if (context->rampRelativePulse == 0UL)
  455. {
  456. nextBoundaryQ32 = context->rampFirstBoundaryQ32;
  457. }
  458. else if (context->rampRelativePulse == 1UL)
  459. {
  460. nextBoundaryQ32 = context->rampSecondBoundaryQ32;
  461. }
  462. else
  463. {
  464. nextBoundaryQ32 = PlsrPlannerPredictedBoundaryQ32(
  465. context, context->rampTargetAreaQ32);
  466. }
  467. desiredDeltaQ32 = (nextBoundaryQ32 > context->rampActualTimeQ32)
  468. ? (nextBoundaryQ32 - context->rampActualTimeQ32)
  469. : 1ULL;
  470. /* The allocated pulse count closes the ramp area exactly. Derive the
  471. physical duration from N/averageHz instead of rounding it to whole
  472. milliseconds; short clipped ramps can be well below 1 ms. */
  473. denominator = (uint64_t)context->rampPulseCount * desiredDeltaQ32;
  474. requestedHz = (denominator == 0ULL)
  475. ? context->rampToHz
  476. : (context->rampTotalAreaQ32
  477. + denominator / 2ULL) / denominator;
  478. if (requestedHz == 0ULL)
  479. {
  480. requestedHz = 1ULL;
  481. }
  482. if (requestedHz > PLSR_FREQUENCY_MAX_HZ)
  483. {
  484. requestedHz = PLSR_FREQUENCY_MAX_HZ;
  485. }
  486. if ((context->lastRampHz != 0UL)
  487. && (((context->rampToHz > context->rampFromHz)
  488. && (requestedHz < context->lastRampHz))
  489. || ((context->rampToHz < context->rampFromHz)
  490. && (requestedHz > context->lastRampHz))))
  491. {
  492. requestedHz = context->lastRampHz;
  493. }
  494. if (PlsrPlannerBuildStep(context, (uint32_t)requestedHz, setting,
  495. requestedFrequencyHz) == 0U)
  496. {
  497. return 0U;
  498. }
  499. denominator = (uint64_t)context->rampPulseCount
  500. * setting->actualFrequencyHz;
  501. actualDeltaQ32 = (denominator == 0ULL)
  502. ? desiredDeltaQ32
  503. : (context->rampTotalAreaQ32
  504. + denominator / 2ULL) / denominator;
  505. context->rampActualTimeQ32 += actualDeltaQ32;
  506. context->rampLastPhaseStepQ32 =
  507. nextBoundaryQ32 - context->rampBoundaryQ32;
  508. context->rampBoundaryQ32 = nextBoundaryQ32;
  509. context->lastRampHz = setting->actualFrequencyHz;
  510. context->rampRelativePulse++;
  511. return 1U;
  512. }
  513. static uint8_t PlsrPlannerTakeStep(PLSR_PLANNER_CONTEXT *context,
  514. PLSR_PLATFORM_TIMER_SETTING *setting,
  515. uint32_t *requestedFrequencyHz,
  516. uint32_t *repeatCount)
  517. {
  518. uint32_t entryEnd = context->entryPulses;
  519. //加速段结束门槛。已经吐出的脉冲 < entryEnd 还在加速。例如加速 1000,这里就是 1000
  520. uint32_t steadyEnd = entryEnd + context->steadyPulses;
  521. //匀速段结束门槛。< steadyEnd 且 ≥ entryEnd 就是匀速。例如再加 5000 匀速,这里就是 6000。再往后是减速
  522. *repeatCount = 1UL;
  523. if (context->generatedPulses >= context->block.pulseBudget)
  524. {
  525. return 0U;
  526. }
  527. if (context->generatedPulses < entryEnd)
  528. { //加速段
  529. if (context->rampKind != 1U)
  530. { // 第一次走进加速
  531. PlsrPlannerStartRamp(context, 1U, context->startHz,context->peakHz, context->entryPulses);
  532. }
  533. return PlsrPlannerTakeRampStep(context, setting,requestedFrequencyHz);
  534. }
  535. if (context->generatedPulses < steadyEnd)
  536. {
  537. *repeatCount = steadyEnd - context->generatedPulses;
  538. context->rampKind = 0U;
  539. return PlsrPlannerBuildStep(context, context->peakHz, setting,
  540. requestedFrequencyHz);
  541. }
  542. if (context->rampKind != 2U)
  543. { // 第一次走进减速
  544. PlsrPlannerStartRamp(context, 2U, context->peakHz,
  545. context->endHz, context->exitPulses);
  546. }
  547. return PlsrPlannerTakeRampStep(context, setting,
  548. requestedFrequencyHz);
  549. }
  550. PLSR_PLANNER_STATUS PlsrPlannerBegin(PLSR_PLANNER_CONTEXT *context,
  551. const PLSR_MOTION_BLOCK *block,
  552. uint32_t appliedHz,
  553. uint64_t phasePulses)
  554. {
  555. uint64_t directRequired;
  556. uint64_t entryRequired;
  557. uint64_t exitRequired;
  558. uint64_t entryWeight;
  559. uint64_t exitWeight;
  560. uint64_t totalWeight;
  561. uint64_t scaledEntry;
  562. if ((context == NULL) || (block == NULL)
  563. || (block->pulseBudget == 0UL)
  564. || (block->referenceSpeedHz == 0UL)
  565. || (block->referenceSpeedHz > PLSR_FREQUENCY_MAX_HZ)
  566. || (block->entryHz > PLSR_FREQUENCY_MAX_HZ)
  567. || (block->cruiseHz == 0UL)
  568. || (block->cruiseHz > PLSR_FREQUENCY_MAX_HZ)
  569. || (block->exitHz > PLSR_FREQUENCY_MAX_HZ)
  570. || (appliedHz > PLSR_FREQUENCY_MAX_HZ)
  571. || (block->curveMode > 2U) || (block->pulseOutput > 3U))
  572. {
  573. return PLSR_PLANNER_INVALID;
  574. }
  575. (void)memset(context, 0, sizeof(*context));
  576. context->block = *block;
  577. context->phasePulses = phasePulses;
  578. context->startHz = (appliedHz != 0UL) ? appliedHz : block->entryHz;
  579. if (context->startHz == 0UL)
  580. {
  581. context->startHz = 1UL;
  582. }
  583. context->endHz = (block->exitHz == 0UL) ? 1UL : block->exitHz;
  584. directRequired = PlsrPlannerRequiredPulses(
  585. block, PlsrPlannerRampWeight(
  586. context->startHz, context->endHz,
  587. PlsrPlannerBaseRampTime(block, context->startHz,
  588. context->endHz)));
  589. if (directRequired > block->pulseBudget)
  590. {
  591. context->peakHz = PlsrPlannerReachableFrequency(
  592. block, context->startHz, context->endHz, block->pulseBudget);
  593. context->endHz = context->peakHz;
  594. context->entryPulses = block->pulseBudget;
  595. context->clipped = 1U;
  596. context->active = 1U;
  597. return PLSR_PLANNER_CLIPPED;
  598. }
  599. context->peakHz = PlsrPlannerPeak(block, context->startHz,
  600. context->endHz);
  601. entryWeight = PlsrPlannerRampWeight(
  602. context->startHz, context->peakHz,
  603. PlsrPlannerBaseRampTime(block, context->startHz, context->peakHz));
  604. exitWeight = PlsrPlannerRampWeight(
  605. context->peakHz, context->endHz,
  606. PlsrPlannerBaseRampTime(block, context->peakHz, context->endHz));
  607. entryRequired = PlsrPlannerRequiredPulses(block, entryWeight);
  608. exitRequired = PlsrPlannerRequiredPulses(block, exitWeight);
  609. if ((entryRequired + exitRequired) <= block->pulseBudget)
  610. {
  611. context->entryPulses = (uint32_t)entryRequired;
  612. context->exitPulses = (uint32_t)exitRequired;
  613. context->steadyPulses = block->pulseBudget
  614. - context->entryPulses
  615. - context->exitPulses;
  616. }
  617. else if (entryRequired == 0ULL)
  618. {
  619. context->exitPulses = block->pulseBudget;
  620. context->clipped = 1U;
  621. }
  622. else if (exitRequired == 0ULL)
  623. {
  624. context->entryPulses = block->pulseBudget;
  625. context->clipped = 1U;
  626. }
  627. else
  628. {
  629. totalWeight = entryWeight + exitWeight;
  630. scaledEntry = ((uint64_t)block->pulseBudget * entryWeight
  631. + totalWeight / 2ULL) / totalWeight;
  632. if (scaledEntry == 0ULL)
  633. {
  634. scaledEntry = 1ULL;
  635. }
  636. if (scaledEntry >= block->pulseBudget)
  637. {
  638. scaledEntry = block->pulseBudget - 1UL;
  639. }
  640. context->entryPulses = (uint32_t)scaledEntry;
  641. context->exitPulses = block->pulseBudget
  642. - context->entryPulses;
  643. context->clipped = 1U;
  644. }
  645. if (context->peakHz != block->cruiseHz)
  646. {
  647. context->clipped = 1U;
  648. }
  649. context->active = 1U;
  650. return (context->clipped != 0U) ? PLSR_PLANNER_CLIPPED
  651. : PLSR_PLANNER_OK;
  652. }
  653. //返回值:实际写了几项(合并后的项数,不是脉冲数)。0 = 没吐出任何东西
  654. uint16_t PlsrPlannerGenerate(PLSR_PLANNER_CONTEXT *context,//规划账本:三段脉冲、已经吐了多少、斜坡面积指针
  655. PLSR_STREAM_ITEM *output,//输出数组,调用方准备好的格子
  656. uint16_t capacity)//这一次最多往 output 里写几项
  657. {
  658. PLSR_PLATFORM_TIMER_SETTING setting;
  659. uint32_t requestedFrequencyHz;
  660. uint32_t repeatCount;
  661. uint16_t produced = 0U;
  662. if ((context == NULL) || (output == NULL) || (capacity == 0U)
  663. || (context->active == 0U))
  664. {
  665. return 0U;
  666. }
  667. while ((produced < capacity)&& (context->generatedPulses < context->block.pulseBudget))
  668. { //输出数组还没写满&&本段预算还没全部交给外面。generatedPulses 按脉冲个数计
  669. if (PlsrPlannerTakeStep(context, &setting, &requestedFrequencyHz, &repeatCount) == 0U)
  670. //本圈 TakeStep 算出的量化后 PSC/ARR/actualHz,先放栈上
  671. {
  672. context->active = 0U;//规划器关掉
  673. break;
  674. }
  675. if ((produced != 0U)
  676. && (PlsrPlannerSameSetting(&output[produced - 1U].setting,&setting) != 0U)
  677. && (output[produced - 1U].requestedFrequencyHz
  678. == requestedFrequencyHz)
  679. && (output[produced - 1U].repeatCount
  680. <= 0xFFFFFFFFUL - repeatCount))
  681. {
  682. output[produced - 1U].repeatCount += repeatCount;
  683. //不用开新格
  684. }
  685. else
  686. {
  687. output[produced].setting = setting;
  688. output[produced].requestedFrequencyHz = requestedFrequencyHz;
  689. output[produced].repeatCount = repeatCount;
  690. produced++;
  691. }
  692. context->generatedPulses += repeatCount;
  693. }
  694. if (context->generatedPulses >= context->block.pulseBudget)
  695. {
  696. context->active = 0U;
  697. }
  698. return produced;
  699. }
  700. static uint64_t PlsrPlannerRampDurationUs(uint32_t pulseCount,
  701. uint32_t fromHz,
  702. uint32_t toHz)
  703. {
  704. uint64_t frequencySum = (uint64_t)fromHz + toHz;
  705. if ((pulseCount == 0UL) || (frequencySum == 0ULL))
  706. {
  707. return 0ULL;
  708. }
  709. return ((uint64_t)2U * pulseCount * 1000000ULL
  710. + frequencySum - 1ULL) / frequencySum;
  711. }
  712. /* Return floor(numerator / denominator * 2^32) without requiring a
  713. 128-bit intermediate. Both operands are bounded by the planner's
  714. 100 kHz Q32 ramp area, so the normalized remainder can be doubled safely. */
  715. static uint32_t PlsrPlannerRatioQ32(uint64_t numerator,
  716. uint64_t denominator)
  717. {
  718. uint64_t remainder;
  719. uint32_t ratio = 0UL;
  720. uint8_t bit;
  721. if ((numerator == 0ULL) || (denominator == 0ULL))
  722. {
  723. return 0UL;
  724. }
  725. if (numerator >= denominator)
  726. {
  727. return 0xFFFFFFFFUL;
  728. }
  729. remainder = numerator;
  730. for (bit = 0U; bit < 32U; bit++)
  731. {
  732. ratio <<= 1U;
  733. remainder <<= 1U;
  734. if (remainder >= denominator)
  735. {
  736. remainder -= denominator;
  737. ratio |= 1UL;
  738. }
  739. }
  740. return ratio;
  741. }
  742. static uint32_t PlsrPlannerRampPulsesAtTime(
  743. const PLSR_PLANNER_CONTEXT *context,
  744. uint32_t pulseCount,
  745. uint32_t fromHz,
  746. uint32_t toHz,
  747. uint64_t elapsedUs,
  748. uint64_t durationUs,
  749. uint64_t *progressQ32)
  750. {
  751. PLSR_PLANNER_CONTEXT ramp = *context;
  752. uint64_t partialAreaQ32;
  753. uint64_t totalAreaQ32;
  754. uint64_t product;
  755. uint32_t areaRatioQ32;
  756. uint32_t result;
  757. if ((pulseCount == 0UL) || (elapsedUs == 0ULL)
  758. || (durationUs == 0ULL))
  759. {
  760. *progressQ32 = 0ULL;
  761. return 0UL;
  762. }
  763. if (elapsedUs >= durationUs)
  764. {
  765. *progressQ32 = PLSR_PLANNER_Q32_ONE;
  766. return pulseCount;
  767. }
  768. *progressQ32 = (elapsedUs * PLSR_PLANNER_Q32_ONE) / durationUs;
  769. ramp.rampFromHz = fromHz;
  770. ramp.rampToHz = toHz;
  771. partialAreaQ32 = PlsrPlannerRampAreaQ32(
  772. &ramp, fromHz, toHz, *progressQ32);
  773. totalAreaQ32 = PlsrPlannerRampAreaQ32(
  774. &ramp, fromHz, toHz, PLSR_PLANNER_Q32_ONE);
  775. areaRatioQ32 = PlsrPlannerRatioQ32(partialAreaQ32,
  776. totalAreaQ32);
  777. product = (uint64_t)pulseCount * areaRatioQ32;
  778. result = (uint32_t)(product >> 32U);
  779. if ((uint32_t)product != 0UL)
  780. {
  781. result++;
  782. }
  783. return (result > pulseCount) ? pulseCount : result;
  784. }
  785. static uint8_t PlsrPlannerSetPredictedFrequency(
  786. const PLSR_PLANNER_CONTEXT *context,
  787. uint32_t fromHz,
  788. uint32_t toHz,
  789. uint64_t progressQ32,
  790. PLSR_PLANNER_TIME_PREDICTION *prediction)
  791. {
  792. PLSR_PLANNER_CONTEXT ramp = *context;
  793. PLSR_PLATFORM_TIMER_SETTING setting;
  794. uint32_t requestedHz;
  795. ramp.rampFromHz = fromHz;
  796. ramp.rampToHz = toHz;
  797. requestedHz = PlsrPlannerInstantFrequency(&ramp, progressQ32);
  798. if (PlsrPlatformBuildTimerSetting(context->block.pulseOutput,
  799. PLSR_OUTPUT_PULSE_DIR,
  800. requestedHz, &setting) == 0U)
  801. {
  802. return 0U;
  803. }
  804. prediction->actualFrequencyHz = setting.actualFrequencyHz;
  805. return 1U;
  806. }
  807. static uint64_t PlsrPlannerRampTargetAreaQ32(uint64_t totalAreaQ32,
  808. uint32_t pulseCount,
  809. uint32_t pulseIndex)
  810. {
  811. uint64_t step = totalAreaQ32 / pulseCount;
  812. uint64_t remainder = totalAreaQ32 % pulseCount;
  813. return step * pulseIndex
  814. + (remainder * pulseIndex) / pulseCount;
  815. }
  816. /* Predict the timer setting of the last complete ramp pulse at the deadline.
  817. A ramp pulse represents the average frequency between two equal-area curve
  818. boundaries; carrying that run setting is closer to the hardware state than
  819. carrying the mathematical instantaneous frequency at the boundary. */
  820. static uint8_t PlsrPlannerSetPredictedRampRunFrequency(
  821. const PLSR_PLANNER_CONTEXT *context,
  822. uint32_t pulseCount,
  823. uint32_t fromHz,
  824. uint32_t toHz,
  825. uint32_t pulseIndex,
  826. PLSR_PLANNER_TIME_PREDICTION *prediction)
  827. {
  828. PLSR_PLANNER_CONTEXT ramp = *context;
  829. PLSR_PLATFORM_TIMER_SETTING setting;
  830. uint64_t totalAreaQ32;
  831. uint64_t previousTargetAreaQ32;
  832. uint64_t targetAreaQ32;
  833. uint64_t previousBoundaryQ32;
  834. uint64_t boundaryQ32;
  835. uint64_t denominator;
  836. uint64_t requestedHz;
  837. if ((pulseCount == 0UL) || (pulseIndex == 0UL))
  838. {
  839. return PlsrPlannerSetPredictedFrequency(
  840. context, fromHz, toHz, 0ULL, prediction);
  841. }
  842. if (pulseIndex > pulseCount)
  843. {
  844. pulseIndex = pulseCount;
  845. }
  846. ramp.rampFromHz = fromHz;
  847. ramp.rampToHz = toHz;
  848. totalAreaQ32 = PlsrPlannerRampAreaQ32(
  849. &ramp, fromHz, toHz, PLSR_PLANNER_Q32_ONE);
  850. previousTargetAreaQ32 = PlsrPlannerRampTargetAreaQ32(
  851. totalAreaQ32, pulseCount, pulseIndex - 1UL);
  852. targetAreaQ32 = PlsrPlannerRampTargetAreaQ32(
  853. totalAreaQ32, pulseCount, pulseIndex);
  854. previousBoundaryQ32 = (pulseIndex == 1UL)
  855. ? 0ULL
  856. : PlsrPlannerExactBoundaryQ32(
  857. &ramp, 0ULL,
  858. previousTargetAreaQ32);
  859. boundaryQ32 = (pulseIndex == pulseCount)
  860. ? PLSR_PLANNER_Q32_ONE
  861. : PlsrPlannerExactBoundaryQ32(
  862. &ramp, previousBoundaryQ32,
  863. targetAreaQ32);
  864. if (boundaryQ32 <= previousBoundaryQ32)
  865. {
  866. return 0U;
  867. }
  868. denominator = (uint64_t)pulseCount
  869. * (boundaryQ32 - previousBoundaryQ32);
  870. requestedHz = (denominator == 0ULL)
  871. ? toHz
  872. : (totalAreaQ32 + denominator / 2ULL)
  873. / denominator;
  874. if (requestedHz == 0ULL)
  875. {
  876. requestedHz = 1ULL;
  877. }
  878. if (requestedHz > PLSR_FREQUENCY_MAX_HZ)
  879. {
  880. requestedHz = PLSR_FREQUENCY_MAX_HZ;
  881. }
  882. if (PlsrPlatformBuildTimerSetting(context->block.pulseOutput,
  883. PLSR_OUTPUT_PULSE_DIR,
  884. (uint32_t)requestedHz,
  885. &setting) == 0U)
  886. {
  887. return 0U;
  888. }
  889. prediction->actualFrequencyHz = setting.actualFrequencyHz;
  890. return 1U;
  891. }
  892. uint8_t PlsrPlannerPredictTime(
  893. const PLSR_PLANNER_CONTEXT *context,
  894. uint32_t elapsedUs,
  895. PLSR_PLANNER_TIME_PREDICTION *prediction)
  896. {
  897. PLSR_PLATFORM_TIMER_SETTING steadySetting;
  898. uint64_t remainingUs = elapsedUs;
  899. uint64_t durationUs;
  900. uint64_t progressQ32;
  901. uint64_t partialPulses;
  902. if ((context == NULL) || (prediction == NULL)
  903. || (context->block.pulseBudget == 0UL))
  904. {
  905. return 0U;
  906. }
  907. (void)memset(prediction, 0, sizeof(*prediction));
  908. durationUs = PlsrPlannerRampDurationUs(
  909. context->entryPulses, context->startHz, context->peakHz);
  910. if ((context->entryPulses != 0UL) && (remainingUs <= durationUs))
  911. {
  912. prediction->pulseCount = PlsrPlannerRampPulsesAtTime(
  913. context, context->entryPulses, context->startHz,
  914. context->peakHz, remainingUs, durationUs, &progressQ32);
  915. prediction->phase = PLSR_PLANNER_PHASE_ENTRY;
  916. prediction->deadlineInProfile = 1U;
  917. return PlsrPlannerSetPredictedRampRunFrequency(
  918. context, context->entryPulses, context->startHz,
  919. context->peakHz, prediction->pulseCount, prediction);
  920. }
  921. if (context->entryPulses != 0UL)
  922. {
  923. remainingUs -= durationUs;
  924. }
  925. if (PlsrPlatformBuildTimerSetting(context->block.pulseOutput,
  926. PLSR_OUTPUT_PULSE_DIR,
  927. context->peakHz,
  928. &steadySetting) == 0U)
  929. {
  930. return 0U;
  931. }
  932. durationUs = (context->steadyPulses == 0UL)
  933. ? 0ULL
  934. : ((uint64_t)context->steadyPulses * 1000000ULL
  935. + steadySetting.actualFrequencyHz - 1UL)
  936. / steadySetting.actualFrequencyHz;
  937. if ((context->steadyPulses != 0UL) && (remainingUs <= durationUs))
  938. {
  939. partialPulses = (remainingUs * steadySetting.actualFrequencyHz
  940. + 999999ULL) / 1000000ULL;
  941. if (partialPulses > context->steadyPulses)
  942. {
  943. partialPulses = context->steadyPulses;
  944. }
  945. prediction->pulseCount = context->entryPulses
  946. + (uint32_t)partialPulses;
  947. prediction->actualFrequencyHz = steadySetting.actualFrequencyHz;
  948. prediction->phase = PLSR_PLANNER_PHASE_STEADY;
  949. prediction->deadlineInProfile = 1U;
  950. return 1U;
  951. }
  952. if (context->steadyPulses != 0UL)
  953. {
  954. remainingUs -= durationUs;
  955. }
  956. durationUs = PlsrPlannerRampDurationUs(
  957. context->exitPulses, context->peakHz, context->endHz);
  958. if ((context->exitPulses != 0UL) && (remainingUs <= durationUs))
  959. {
  960. partialPulses = PlsrPlannerRampPulsesAtTime(
  961. context, context->exitPulses, context->peakHz,
  962. context->endHz, remainingUs, durationUs, &progressQ32);
  963. prediction->pulseCount = context->entryPulses
  964. + context->steadyPulses
  965. + (uint32_t)partialPulses;
  966. prediction->phase = PLSR_PLANNER_PHASE_EXIT;
  967. prediction->deadlineInProfile = 1U;
  968. return PlsrPlannerSetPredictedRampRunFrequency(
  969. context, context->exitPulses, context->peakHz,
  970. context->endHz, (uint32_t)partialPulses, prediction);
  971. }
  972. prediction->pulseCount = context->block.pulseBudget;
  973. prediction->phase = PLSR_PLANNER_PHASE_COMPLETE;
  974. prediction->deadlineInProfile = 0U;
  975. return PlsrPlannerSetPredictedFrequency(
  976. context, context->endHz, context->endHz,
  977. PLSR_PLANNER_Q32_ONE, prediction);
  978. }